# Vmcp

> tool graphql aggregation

- **Type:** MCP server
- **Install:** `agentstack add mcp-hewimetall-vmcp`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [hewimetall](https://agentstack.voostack.com/s/hewimetall)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [hewimetall](https://github.com/hewimetall)
- **Source:** https://github.com/hewimetall/vmcp

## Install

```sh
agentstack add mcp-hewimetall-vmcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# vmcp

[](https://github.com/hewimetall/vmcp/actions/workflows/coverage.yml)
[](https://github.com/hewimetall/vmcp/actions/workflows/coverage.yml)

A virtual MCP gateway that aggregates many upstream MCP servers behind a
single GraphQL endpoint.

Rust workspace, 9 crates. Speaks the Model Context Protocol over streamable
HTTP and exposes the union of all upstream tools as one GraphQL schema. An
agent makes one `query_graphql` call instead of N+1 round-trips across
individual MCP tools.

## What it does

- **One primary MCP tool, `query_graphql`** — clients send a GraphQL document,
  vmcp fans out to upstreams in parallel via aliased selection sets. Read tools
  (`Query`) aggregate **in parallel**; write tools (`Mutation`) aggregate
  **sequentially** per the GraphQL spec — see
  [`docs/mcp-aggregation-workshop.md`](docs/mcp-aggregation-workshop.md).
- **Optional `run_task` (SEP-1686)** — when `[tasks]` is enabled, long-running
  upstream tools marked with `taskSupport` can be invoked as durable SQLite-backed
  tasks (`tasks/get` / `tasks/result`). GraphQL stays the sync path. See
  [`docs/tasks.md`](docs/tasks.md).
- **Lazy discovery ladder** — `prompts/list` (skill playbooks) →
  `{ servers }` → `{ search(q) }` (includes `taskSupport`) → `__type(name)` →
  call. No deep `__schema` dumps.
- **Dynamic schema** built at boot from upstream `tools/list`. Each upstream
  `foo` gets `FooRead` under `Query.foo` and `FooWrite` under `Mutation.foo`,
  partitioned by `readOnlyHint`.
- **Hot swap on drift** — registered upstream tool set changes are detected
  and the schema is replaced atomically via `Arc>`.
- **OAuth 2.1 + PKCE + DCR** — argon2id master-password consent, locally
  rotated JWKS, JWT bearer on `/mcp`.

## Documentation

Full operator guide: **[`docs/README.md`](docs/README.md)**

| Topic | Doc |
| ----- | --- |
| Docker / TLS / production (GHCR bootstrap) | [`docs/deployment.md`](docs/deployment.md) |
| OAuth, master password, static tokens | [`docs/authentication.md`](docs/authentication.md) |
| Cargo features, HTTP vs stdio | [`docs/builds-and-modes.md`](docs/builds-and-modes.md) |
| Upstream registry (services, tools, prompts) | [`docs/upstreams.md`](docs/upstreams.md) |
| Native MCP Tasks (`run_task` + SQLite) | [`docs/tasks.md`](docs/tasks.md) |
| Admin sessions & recordings (JSON dirs) | [`docs/sessions.md`](docs/sessions.md) |
| Skill playbooks (YAML → MCP prompts) | [`docs/skills.md`](docs/skills.md) |
| Cursor, Claude / `.mcpb`, curl | [`docs/clients.md`](docs/clients.md) |
| Aggregation bench (Python) | [`docs/bench.md`](docs/bench.md) |

## Quick start

Prebuilt **binaries** and a **Docker image** ship on every `v*` tag
([Releases](https://github.com/hewimetall/vmcp/releases) ·
`ghcr.io/hewimetall/vmcp`). Latest: **v0.6.3**.

### MCP Bundle (`.mcpb`) — one-click local install

Claude Desktop (and other [MCPB](https://github.com/modelcontextprotocol/mcpb) hosts) can install a packaged stdio server:

1. Download `vmcp-0.6.3-.mcpb` from the [Releases](https://github.com/hewimetall/vmcp/releases) page (e.g. `linux-x86_64`, `macos-aarch64`).
2. Double-click / drag into Claude Desktop, or **Settings → Extensions → Install Extension…**.

Needs Node on `PATH` for the demo `npx` upstream. Details: [`docs/clients.md`](docs/clients.md).

### Binary (HTTP gateway, local try)

Needs Node only if you keep the demo `npx` upstream.

```bash
curl -fsSL -o vmcp.tgz \
  "https://github.com/hewimetall/vmcp/releases/download/v0.6.3/vmcp-0.6.3-linux-x86_64.tar.gz"
tar -xzf vmcp.tgz
VMCP_REGISTRY_PATH=./demo/registry.json \
VMCP_SPEC_DIR=./demo/specs \
VMCP_SKILLS_DIR=./demo/skills \
./vmcp --config ./vmcp.toml
```

Other OS/arch assets (and `vmcp-stdio-*`) are on the same release page.

### Docker / VPS

```bash
docker pull ghcr.io/hewimetall/vmcp:0.6.3
# TLS stack (Caddy + Let's Encrypt) from the published image:
./deploy/bootstrap.sh --domain gateway.example.com --tag 0.6.3
```

Details: [`docs/deployment.md`](docs/deployment.md). The runtime image has no
Node — swap `demo/registry.json` for HTTP/binary upstreams in production.

### From source

Requires Rust 1.80+ (and Node for the demo `npx` upstream).

```bash
cargo run -p vmcp
```

Either way, vmcp listens on `http://127.0.0.1:8765`:

- `/mcp` — MCP streamable HTTP endpoint (bearer-authenticated)
- `/health` — liveness probe, returns `ok`
- `/.well-known/oauth-authorization-server`, `/authorize`, `/consent`,
  `/token`, `/register`, `/.well-known/jwks.json` — OAuth surface

The default `demo/registry.json` spawns one upstream
(`@agentmemory/mcp` via `npx`). Point your MCP client at
`http://127.0.0.1:8765/mcp` and complete the OAuth flow; the default master
password is `demo-master` (rotate before deploying anywhere real).

## Build variants (cargo features)

The single `vmcp` binary is partitioned by compile-time features so you can
ship a slim stdio client without the HTTP/admin surface:

| Feature | Default | Enables |
| ------- | ------- | ------- |
| `web`   | yes     | HTTP gateway ingress: Axum listener, OAuth surface, session recorder, transparent proxy. |
| `admin` | yes     | Admin SPA (`/admin`). Implies `web`. |

`stdio` mode and the utility subcommands (`hash-password`, `pre-reg`,
`print-config`) are always available.

```bash
cargo build --release -p vmcp                                  # full: web + admin (default)
cargo build --release -p vmcp --no-default-features --features web  # web, no admin UI
cargo build --release -p vmcp --no-default-features            # stdio-minimal (no HTTP, no admin)
```

Prebuilt binaries, `.mcpb` bundles (stdio + demo data), and `ghcr.io/hewimetall/vmcp`
are published on every `v*` tag — see [Quick start](#quick-start). A local Docker
build can also target the stdio-minimal variant:
`docker build --target runtime --build-arg FEATURES="--no-default-features" -t vmcp:stdio .`

## Configuration

Edit `vmcp.toml` (see inline comments). Every key is overridable via env
vars with the `VMCP_` prefix and `__` as nested separator, e.g.

```bash
VMCP_AUTH__MASTER_PASSWORD_ARGON2='$argon2id$...' cargo run -p vmcp
```

Generate a password hash:

```bash
cargo run -p vmcp -- hash-password --password 'your-secret'
```

Print the resolved config and exit:

```bash
cargo run -p vmcp -- print-config
```

### Pre-registered eternal tokens

The normal OAuth flow issues short-lived JWTs signed by a rotating, in-memory
JWKS key — so **every restart and key rotation invalidates outstanding
tokens**. That's correct for browser clients but painful for a CI job or a demo
client that just wants one credential that keeps working across redeploys.

`pre-reg` mints an opaque, **non-expiring** bearer token (`vmcp_`) and
appends it to a JSON file:

```bash
cargo run -p vmcp -- pre-reg --name ci --scope mcp:use --out ./tokens.json
# prints: vmcp_xK3v...   (the token, on stdout)
```

Point the gateway at the file and the token is accepted on `/mcp` directly,
bypassing OAuth:

```toml
[auth]
tokens_file = "./tokens.json"
```

```bash
curl -H "Authorization: Bearer vmcp_xK3v..." http://127.0.0.1:8765/mcp
```

The file is **hot-reloaded** — add or remove a token and the change takes
effect without a restart. **Revocation = delete the token's line from the
file.** These are god-keys with full gateway access and no expiry: treat the
file as a secret (`pre-reg` writes it `0600` on unix; it's git-ignored by
default). The OAuth flow keeps working alongside this — a `vmcp_`-prefixed
bearer takes the static path, anything else is verified as a JWT.

> Not to be confused with the admin UI's `pre_registered` session state, which
> refers to OAuth DCR clients (RFC 7591), a separate mechanism.

### Stdio mode (Claude Desktop / Cursor)

For single-client hosts that speak MCP over stdin/stdout instead of HTTP:

```bash
cargo run -p vmcp -- stdio --config /path/vmcp.toml
```

Requires exactly **one** token in `auth.tokens_file` (create with `pre-reg`)
or set `VMCP_STDIO_CLIENT_ID` for local dev. Example `mcp.json`:

```json
{
  "mcpServers": {
    "vmcp": {
      "command": "vmcp",
      "args": ["stdio", "--config", "/path/vmcp.toml"],
      "env": { "RUST_LOG": "info" }
    }
  }
}
```

Stdio mode skips OAuth, admin, and HTTP entirely. The pipe is the trust
boundary — the static token identifies the client in logs, not as a per-request
bearer check.

### Disabling HTTP auth (local dev only)

Set `auth.enabled = false` (or `VMCP_AUTH__ENABLED=false`) to mount `/mcp`
without bearer middleware and hide `/admin`. **Never use on untrusted networks.**

## Workspace layout

| Crate            | Purpose                                                                  |
| ---------------- | ------------------------------------------------------------------------ |
| `vmcp`           | Entry binary. Wires axum + rmcp + every library crate.                   |
| `vmcp-config`    | Config loading (figment + TOML + env override).                          |
| `vmcp-registry`  | `registry.json`, sidecar specs, `tools.lock.json`.                       |
| `vmcp-upstream`  | Upstream pool — stdio child-process MCP clients via rmcp.                |
| `vmcp-graphql`   | Dynamic GraphQL schema generation from upstream `tools/list`.            |
| `vmcp-auth`      | OAuth 2.1 + PKCE + DCR, argon2id, JWKS rotation, `require_bearer`.       |
| `vmcp-server`    | MCP surface (`query_graphql`, optional `run_task` + SQLite TaskStore), skills, proxy. |
| `vmcp-notify`    | In-process notification ring buffer (tokio broadcast).                   |
| `vmcp-admin`     | Admin UI + recording/playback.                                           |

## License

MIT — see [LICENSE](LICENSE).

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [hewimetall](https://github.com/hewimetall)
- **Source:** [hewimetall/vmcp](https://github.com/hewimetall/vmcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-hewimetall-vmcp
- Seller: https://agentstack.voostack.com/s/hewimetall
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
