{"id":45398159,"url":"https://github.com/NimbleBrainInc/mpak","last_synced_at":"2026-03-06T20:01:36.011Z","repository":{"id":337821430,"uuid":"1153317249","full_name":"NimbleBrainInc/mpak","owner":"NimbleBrainInc","description":"Open-source package registry for MCP (Model Context Protocol) servers with built-in security scanning, trust scoring (L1-L4), and CLI. Every bundle verified across 25 supply-chain controls.","archived":false,"fork":false,"pushed_at":"2026-02-26T14:55:38.000Z","size":1164,"stargazers_count":0,"open_issues_count":18,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-26T20:04:58.949Z","etag":null,"topics":["ai-agents","ai-tools","claude-code","claude-desktop","cli","kubernetes","mcp","mcp-server","mcp-servers","model-context-protocol","open-source","package-manager","package-registry","python","sbom","security-scanning","self-hosted","supply-chain-security","typescript","vulnerability-scanning"],"latest_commit_sha":null,"homepage":"https://mpak.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NimbleBrainInc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-09T06:46:56.000Z","updated_at":"2026-02-20T08:36:32.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/NimbleBrainInc/mpak","commit_stats":null,"previous_names":["nimblebraininc/mpak"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/NimbleBrainInc/mpak","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NimbleBrainInc%2Fmpak","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NimbleBrainInc%2Fmpak/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NimbleBrainInc%2Fmpak/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NimbleBrainInc%2Fmpak/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NimbleBrainInc","download_url":"https://codeload.github.com/NimbleBrainInc/mpak/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NimbleBrainInc%2Fmpak/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30195529,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","ai-tools","claude-code","claude-desktop","cli","kubernetes","mcp","mcp-server","mcp-servers","model-context-protocol","open-source","package-manager","package-registry","python","sbom","security-scanning","self-hosted","supply-chain-security","typescript","vulnerability-scanning"],"created_at":"2026-02-21T19:44:50.174Z","updated_at":"2026-03-06T20:01:36.003Z","avatar_url":"https://github.com/NimbleBrainInc.png","language":"TypeScript","funding_links":[],"categories":["Build Tools"],"sub_categories":[],"readme":"# mpak\n\n[![mpak.dev](https://mpak.dev/badge.svg)](https://mpak.dev) [![CI](https://github.com/NimbleBrainInc/mpak/actions/workflows/ci.yml/badge.svg)](https://github.com/NimbleBrainInc/mpak/actions/workflows/ci.yml)\n\nThe open source package registry for [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) servers. Every bundle scanned, every install scored.\n\nmpak provides three things:\n\n1. **MCPB** (MCP Bundle), a standardized package format for MCP servers with declared dependencies, locked versions, and reproducible installs.\n2. **MTF** (mpak Trust Framework), a security scanner that scores every bundle across supply chain, code quality, artifact integrity, and provenance controls.\n3. **A self-hostable registry** that stores, serves, and scores MCPB bundles. Use the public instance at [mpak.dev](https://mpak.dev) or run your own.\n\n## Why this exists\n\nMCP is the open protocol that lets AI agents call external tools. An MCP server exposes capabilities (API calls, file access, database queries) that agents invoke at runtime. That means MCP servers get privileged access to AI agent execution environments. A compromised server means arbitrary code execution inside your workflow.\n\nThe MCP ecosystem has no standardized supply chain security. Servers are distributed as loose scripts, GitHub repos, npm packages, and Docker images with no consistent packaging and no verification of what they contain before they run. The official MCP Registry indexes thousands of servers but makes no claims about their safety.\n\nDiscovery is solved. Trust is not. mpak handles what comes after discovery: packaging, verification, distribution, and governance.\n\n## Concepts\n\n### Bundles\n\nA bundle is a `.mcpb` file (a ZIP archive) that contains everything needed to run an MCP server:\n\n```\nmy-server.mcpb\n├── manifest.json     # Metadata: name, version, server_type, how to run it\n├── src/              # Server source code\n└── deps/             # All dependencies, vendored\n```\n\n`manifest.json` is the required entry point. It declares the package name, version, server type (`node`, `python`, or `binary`), platform-specific run commands, and the tools/prompts/resources the server exposes. The schema is defined in `packages/schemas`.\n\n### Skills\n\nSkills are the knowledge counterpart to bundles. While bundles give an AI agent the ability to *do* things (call APIs, run commands), skills give it the ability to *think* about things (domain expertise, workflow instructions).\n\nA skill is a markdown file (`SKILL.md`) with YAML frontmatter that declares metadata (name, description, category, trigger phrases). Skills can be packaged as `.skill` files (also ZIP archives) and distributed through the registry.\n\n### Trust levels\n\nEvery bundle receives a trust score from the MTF scanner. The score has two parts: a level (L1 through L4) and a numeric score (0 to 100) representing how many controls passed within that level. See the full framework at [mpaktrust.org](https://mpaktrust.org).\n\n| Level | Name | Controls | What it means |\n|-------|------|----------|---------------|\n| **L1** | Basic | 5 | SBOM generated, no secrets or malware detected, valid manifest, tools declared |\n| **L2** | Standard | 15 | Adds vulnerability scanning, dependency pinning, static analysis, author identity |\n| **L3** | Verified | 22 | Adds bundle signatures, build attestation, input validation, repo health checks |\n| **L4** | Attested | 25 | Adds behavioral analysis, reproducible builds, commit linkage |\n\nIn the CLI output, `L3 87` means the bundle reached Level 3 and passed 87% of L3 controls.\n\n### Publishing\n\nBundles are published through GitHub Actions, not the CLI. A GitHub Actions workflow calls `POST /v1/bundles/announce` with a GitHub OIDC token. The registry verifies the token, downloads the release artifact from GitHub, validates the SHA256 hash, stores the bundle, and triggers an MTF security scan. This design ensures every published bundle has a verifiable link back to a source repository and CI run.\n\n### Claiming\n\nClaiming lets a maintainer prove they own a package. To claim `@scope/my-server`, add a `mpak.json` file to your GitHub repo:\n\n```json\n{\n  \"name\": \"@scope/my-server\",\n  \"maintainers\": [\"your-github-username\"]\n}\n```\n\nThen call the claim endpoint. The registry verifies the file exists in your repo with matching metadata. Once claimed, only the claimer (or the repo owner) can publish new versions.\n\n## Quickstart\n\nInstall the CLI:\n\n```bash\nnpm install -g @nimblebrain/mpak\n```\n\nSearch for a bundle:\n\n```bash\nmpak search github\n\n# NAME                      VERSION   TRUST    DESCRIPTION\n# @anthropic/github-mcp     1.2.0     L3 87    GitHub API integration\n# community/github-issues   2.0.1     L4 94    Issue management\n```\n\nPull and run it:\n\n```bash\nmpak bundle run @anthropic/github-mcp\n```\n\nThe CLI downloads the bundle from mpak.dev, extracts it to `~/.mpak/cache/`, and starts the MCP server.\n\n### Use with Claude Desktop\n\nAdd a server to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):\n\n```json\n{\n  \"mcpServers\": {\n    \"github\": {\n      \"command\": \"mpak\",\n      \"args\": [\"bundle\", \"run\", \"@anthropic/github-mcp\"]\n    }\n  }\n}\n```\n\n### Use with Claude Code\n\n```bash\nclaude mcp add github -- mpak bundle run @anthropic/github-mcp\n```\n\n## Repository structure\n\nThis is a monorepo managed with [pnpm workspaces](https://pnpm.io/workspaces) and [Turborepo](https://turbo.build/).\n\n```\npackages/\n  schemas/       Zod schemas and TypeScript types (foundation for everything else)\n  sdk/           TypeScript client for the registry API\n  cli/           The `mpak` CLI\n\napps/\n  registry/      Fastify API server with Prisma/PostgreSQL\n  web/           React + Vite web UI (browse, search, trust scores)\n  scanner/       MTF security scanner (Python)\n  docs/          Documentation site (Astro/Starlight)\n\ndeploy/\n  docker/        Docker Compose for local dev and production\n  kubernetes/    Helm chart\n\nscripts/\n  setup.sh       One-time dev environment setup\n  dev.sh         Start all services for local development\n  test.sh        Run the full test suite\n  release.sh     Version bump, changelog, publish\n```\n\n### Dependency graph\n\n```\nschemas  (no internal deps)\n   ↓\n  sdk    (depends on schemas)\n   ↓\n  cli    (depends on sdk + schemas)\n\nregistry (depends on schemas, standalone Fastify server)\nweb      (standalone React app, talks to registry API)\nscanner  (standalone Python project, not in pnpm workspaces)\n```\n\n## Packages\n\n### `packages/schemas`\n\nZod schemas and inferred TypeScript types for the MCPB manifest format, API responses, trust scores, skills, and validation helpers. This is the source of truth for data shapes across the entire stack.\n\n**Key exports:** `BundleSchema`, `SkillSchema`, `MpakJsonSchema`, `SearchParamsSchema`, validation functions.\n\n### `packages/sdk-typescript`\n\nTypeScript SDK for interacting with a mpak registry. Wraps the HTTP API with typed methods for searching, downloading, and inspecting bundles and skills.\n\n```typescript\nimport { MpakClient } from \"@nimblebrain/mpak-sdk\";\n\nconst client = new MpakClient(); // defaults to https://mpak.dev\nconst results = await client.searchBundles(\"github\");\nconst bundle = await client.getBundleDetails(\"@anthropic/github-mcp\");\n```\n\n### `packages/cli`\n\nThe `mpak` command-line tool. Built with [Commander.js](https://github.com/tj/commander.js/).\n\n| Command | Description |\n|---------|-------------|\n| `mpak search \u003cquery\u003e` | Search bundles and skills |\n| `mpak bundle search \u003cquery\u003e` | Search bundles only |\n| `mpak bundle show \u003cname\u003e` | Show bundle details and trust score |\n| `mpak bundle pull \u003cname\u003e` | Download a bundle |\n| `mpak bundle run \u003cname\u003e` | Download and run an MCP server |\n| `mpak skill search \u003cquery\u003e` | Search skills |\n| `mpak skill show \u003cname\u003e` | Show skill details |\n| `mpak skill install \u003cname\u003e` | Install a skill to `~/.claude/skills/` |\n| `mpak skill validate \u003cpath\u003e` | Validate a skill directory |\n| `mpak skill pack \u003cpath\u003e` | Create a `.skill` bundle |\n| `mpak config set \u003cpkg\u003e \u003ckey=value\u003e` | Set config for a package |\n| `mpak config get \u003cpkg\u003e` | Show config for a package |\n\n## Apps\n\n### `apps/registry`\n\nThe registry API server. Fastify with Prisma ORM on PostgreSQL. Handles bundle storage, downloads, trust score tracking, and the MTF scanning pipeline.\n\n**API surface:**\n\n- `/v1/bundles/*` - Native mpak API for bundle operations\n- `/v1/skills/*` - Native mpak API for skill operations\n- `/v0.1/servers` - MCP Registry spec compatibility (so MCP clients can discover bundles through the standard protocol)\n- `/app/*` - Routes used by the web UI (auth, admin, package claiming, scan results)\n- `/health` - Health check\n- `/docs` - OpenAPI/Swagger documentation\n\n**Storage backends:** Local filesystem, S3, GCS, Azure Blob Storage. Configured via environment variables.\n\n**Auth:** Clerk (OIDC). Optional for read endpoints, required for publish.\n\n### `apps/web`\n\nReact SPA for browsing the registry. Built with Vite, Tailwind CSS 4, React Router, and TanStack Query. Includes trust score visualization, bundle details, skill browsing, and an admin panel.\n\n### `apps/scanner`\n\nPython security scanner implementing the mpak Trust Framework (MTF). Evaluates bundles against 20+ controls across five domains:\n\n| Domain | Controls | What it checks |\n|--------|----------|----------------|\n| Supply Chain (SC) | SC-01 through SC-03 | SBOM, vulnerability scanning, dependency pinning |\n| Code Quality (CQ) | CQ-01 through CQ-06 | Secrets, malicious patterns, static analysis, unsafe execution |\n| Artifact Integrity (AI) | AI-01, AI-02 | Manifest validation, content hashes |\n| Provenance (PR) | PR-01, PR-02 | Repository verification, author identity |\n| Capability Declaration (CD) | CD-01 through CD-03 | Tool descriptions, permission scopes |\n\nProduces a trust score from L1 (Basic) to L4 (Attested) based on which controls pass. See [Trust levels](#trust-levels) for details on each level.\n\n**How scanning works:** When a bundle is published, the registry creates a Kubernetes Job that runs the scanner image. The scanner evaluates the bundle, writes results to S3, and POSTs the score back to the registry via a callback URL. In Docker Compose, the scanner runs as a standalone container instead of a K8s Job.\n\n### `apps/docs`\n\nDocumentation site. Covers CLI usage, bundle format, skills, integrations (VS Code, Claude Desktop, Cursor, Claude Code), and security controls.\n\n## Development setup\n\n### Prerequisites\n\n- Node.js 22+\n- pnpm 9+\n- PostgreSQL 16+\n- Python 3.13+ and [uv](https://docs.astral.sh/uv/) (for the scanner)\n\n### 1. Install dependencies\n\n```bash\npnpm install\n```\n\n### 2. Set up PostgreSQL\n\nIf you already have PostgreSQL running locally:\n\n```bash\npsql -c \"CREATE USER mpak WITH PASSWORD 'mpak' CREATEDB;\"\npsql -c \"CREATE DATABASE mpak OWNER mpak;\"\n```\n\nOr start one with Docker:\n\n```bash\ndocker run -d --name mpak-postgres \\\n  -e POSTGRES_USER=mpak -e POSTGRES_PASSWORD=mpak -e POSTGRES_DB=mpak \\\n  -p 5432:5432 postgres:16-alpine\n```\n\n### 3. Configure environment\n\nEach app that needs configuration has its own `.env.example`. Copy them:\n\n```bash\ncp apps/registry/.env.example apps/registry/.env\ncp apps/web/.env.example apps/web/.env\n```\n\nThe defaults work for local development with no changes needed.\n\n### 4. Run database migrations\n\n```bash\ncd apps/registry \u0026\u0026 npx prisma migrate dev \u0026\u0026 cd ../..\n```\n\n### 5. Seed example data\n\nPopulate the database with example skills so the UI has something to show:\n\n```bash\ncd apps/registry \u0026\u0026 npm run db:seed \u0026\u0026 cd ../..\n```\n\nThis inserts a handful of real skills (`@nimblebraininc/docs-auditor`, `@nimblebraininc/seo-optimizer`, `@nimblebraininc/strategic-thought-partner`) with multiple versions, download counts, tags, and triggers. Safe to run multiple times (uses upserts).\n\nTo add more seed data, edit `apps/registry/prisma/seed.ts`.\n\n### 6. Build\n\n```bash\npnpm build\n```\n\n### Running services\n\nStart services individually. Each runs in its own terminal:\n\n```bash\n# Registry API (port 3200)\npnpm --filter @nimblebrain/mpak-registry dev\n\n# Web UI (port 5173)\npnpm --filter @nimblebrain/mpak-web dev\n\n# Docs site (port 4321)\npnpm --filter mpak-docs dev\n```\n\nVerify the registry is running:\n\n```bash\ncurl http://localhost:3200/health\n```\n\n### Running with Docker Compose\n\n```bash\ndocker compose -f deploy/docker/docker-compose.yml up --build\n```\n\n| Service | Port | Description |\n|---------|------|-------------|\n| `postgres` | 5432 | PostgreSQL 16 |\n| `registry` | 3200 | Registry API |\n| `web` | 8080 | Web UI (nginx) |\n| `scanner` | - | MTF scanner (CLI tool) |\n\n### Running tests\n\n```bash\n# All TypeScript tests\npnpm test\n\n# Specific package\npnpm --filter @nimblebrain/mpak-schemas test\npnpm --filter @nimblebrain/mpak-sdk test\npnpm --filter @nimblebrain/mpak test       # CLI\n\n# Python scanner tests\ncd apps/scanner \u0026\u0026 uv sync --dev \u0026\u0026 uv run pytest\n\n# Full verification (build + test + lint + typecheck)\npnpm build \u0026\u0026 pnpm test \u0026\u0026 pnpm lint \u0026\u0026 pnpm typecheck\n```\n\n### Build\n\n```bash\n# Build all packages (respects dependency order via Turborepo)\npnpm build\n\n# Build a specific package\npnpm --filter @nimblebrain/mpak-schemas build\n\n# CLI smoke test after building\nnode packages/cli/dist/index.js --help\n```\n\n## Environment variables\n\nEach app manages its own `.env` file. There is no root `.env`.\n\n### `apps/registry/.env`\n\nSee [`apps/registry/.env.example`](apps/registry/.env.example) for the full list. Key variables:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `DATABASE_URL` | `postgresql://mpak:mpak@localhost:5432/mpak` | PostgreSQL connection string |\n| `PORT` | `3200` | Registry server port |\n| `STORAGE_TYPE` | `local` | Bundle storage: `local` or `s3` |\n| `STORAGE_PATH` | `./packages` | Local storage path (when `STORAGE_TYPE=local`) |\n| `CLERK_SECRET_KEY` | (empty) | Clerk auth secret. Optional for local dev, required in production |\n| `SCANNER_ENABLED` | `false` | Enable MTF scanning on publish |\n| `SCANNER_CALLBACK_URL` | `http://localhost:3200/app/scan-results` | URL the scanner POSTs results to. Set to your cluster-internal service address in K8s |\n| `SCANNER_SECRET_NAME` | `scanner-secrets` | Name of the K8s Secret mounted into scanner Jobs |\n\n### `apps/web/.env`\n\nSee [`apps/web/.env.example`](apps/web/.env.example) for the full list.\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `VITE_API_URL` | `http://localhost:3200` | Registry API endpoint |\n| `VITE_CLERK_PUBLISHABLE_KEY` | (empty) | Clerk public key. Optional for local dev |\n| `VITE_ENABLE_DEBUG_AUTH` | `true` | Show auth debug panel in UI |\n\n## Deployment\n\n### Database migrations\n\nRun Prisma migrations directly:\n\n```bash\n# Check migration status\ncd apps/registry \u0026\u0026 DATABASE_URL=\"postgresql://...\" npx prisma migrate status\n\n# Run pending migrations\ncd apps/registry \u0026\u0026 DATABASE_URL=\"postgresql://...\" npx prisma migrate deploy\n```\n\n### Helm\n\n```bash\nhelm lint deploy/kubernetes/helm/mpak/\nhelm install mpak deploy/kubernetes/helm/mpak/ \\\n  --set config.databaseUrl=\"postgresql://...\" \\\n  --set config.storageBackend=s3\n```\n\nThe Helm chart supports `existingSecret` for production secrets management.\n\n### Docker (production)\n\n```bash\ndocker compose -f deploy/docker/docker-compose.prod.yml up -d\n```\n\nUses pre-built images with S3 storage and proper resource limits.\n\n## Architecture\n\n```\n                    ┌─────────────┐\n                    │   Web UI    │  React SPA\n                    │  (Vite)     │  Browse, search, trust scores\n                    └──────┬──────┘\n                           │ HTTP\n                           ▼\n┌─────────┐       ┌─────────────┐       ┌──────────┐\n│   CLI   │──────▶│  Registry   │──────▶│ Storage  │\n│ (mpak)  │ HTTP  │  (Fastify)  │       │ (S3/GCS/ │\n└─────────┘       └──────┬──────┘       │  local)  │\n                         │              └──────────┘\n                    ┌────┴────┐\n                    │         │\n                    ▼         ▼\n              ┌──────────┐ ┌─────────┐\n              │PostgreSQL│ │ Scanner │\n              │ (Prisma) │ │ (Python)│\n              └──────────┘ └─────────┘\n```\n\nThe CLI and web UI both talk to the registry API. The registry stores bundles in configurable storage (S3, GCS, Azure, or local filesystem) and metadata in PostgreSQL. Bundles are published via GitHub Actions OIDC (not the CLI). When a bundle is published, the registry creates a Kubernetes Job running the scanner. The scanner evaluates MTF controls, writes detailed results to S3, and POSTs the trust score back to the registry via a callback URL.\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for development workflow, commit conventions, and code style guidelines.\n\n## License\n\nApache 2.0. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNimbleBrainInc%2Fmpak","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FNimbleBrainInc%2Fmpak","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FNimbleBrainInc%2Fmpak/lists"}