Get started
Get started

Quickstart

Boot a working MCPG gateway in under five minutes — generate a validated dev config, check it, run the gateway, and curl /health.

This gets you from nothing to a running gateway answering health checks in under five minutes. No external services, no auth — a single-node dev config on loopback.

Just want to click around? The control-plane server has a one-command dev wedge: mcpg cp serve --dev boots the control plane + an embedded dashboard on http://127.0.0.1:7843 (gRPC on :7844) with loopback auth_mode=none, and stores its state (sqlite db) in ~/.mcpg. That gives you the fleet dashboard, not a serving gateway — to expose MCP tools you still run a gateway, which is exactly what the rest of this page walks through.

You'll use three commands that ship in the mcpg crate:

  • mcpg config init — scaffold a validated starter config from a template
  • mcpg config check — validate a config before booting
  • mcpg — the gateway itself

First, get the binaries. Build from source, grab the release tarball, or use the Docker image — see Install. The commands below assume mcpg, mcpg config init, and mcpg config check are on your PATH. From a source checkout, prefix each with cargo run -q -p mcpg --bin <name> --.

1. Generate a dev config

The dev-single-node template is built for a laptop: a mock tool that answers from config alone and an http tool that calls a real endpoint, stderr JSON logs, audit on, and anonymous identity (fine on loopback).

bash
mcpg config init --template dev-single-node --output dev.yaml
ini
✓ Wrote dev.yaml (dev-single-node).
  Validate:  mcpg config check dev.yaml
  Boot:      MCPG_CONFIG=dev.yaml mcpg

Run mcpg config init --list to see all templates (dev-single-node, production-single-redis, production-redis-cluster, production-nats-cluster, air-gapped, multi-tenant).

The generated dev.yaml is small and readable. The shape is the real schema — note the top-level keys gateway, cluster, plugins, mcp, and observability:

yaml
gateway:
  server:
    bind_address: "127.0.0.1:8787"
    mcp_path: "/mcp"
    health_path: "/health"
    allowed_origins: []

cluster:
  kind: single_node

plugins:
  - id: dev.mcpg.backend.mock
    class: backend
    source:
      oci: "ghcr.io/mcpg-dev/source-code/plugins/backend-mock:0.0.1-alpha.10"
  - id: dev.mcpg.backend.http
    class: backend
    source:
      oci: "ghcr.io/mcpg-dev/source-code/plugins/backend-http:0.0.1-alpha.10"

mcp:
  capabilities:
    tools:
      - name: dev.mock.echo
        description: Echo a JSON value back as the tool result.
        governance:
          minimum_trust: unauthenticated
        backend:
          kind: mock
          response: { ok: true, source: "dev-single-node" }

      - name: dev.http.get
        description: Fetch a URL and return the response body.
        governance:
          minimum_trust: unauthenticated
        backend:
          kind: http
          url: "https://example.com/"
          method: GET

observability:
  logs:
    level: info
    sinks:
      - kind: stderr
        config: { format: json }

Every backend is a plugin, including mock — nothing is linked into the binary. The plugins: block is what makes kind: mock and kind: http resolvable; drop it and the bindings have no implementation to bind to. The gateway pulls each reference at boot, so the first run needs registry access.

2. Validate it

The gateway rejects unknown fields at boot, so validate before you run. This catches typos and stale keys up front.

bash
mcpg config check dev.yaml
csharp
✓ dev.yaml: valid (2 bindings, 2 plugins, audit on, observability on)

Exit code 0 and valid means you're good to boot.

3. Boot the gateway

The gateway reads its config path from the MCPG_CONFIG environment variable:

bash
MCPG_CONFIG=dev.yaml mcpg

It binds to 127.0.0.1:8787, pulls the two backend plugins, loads both tools, and starts logging to stderr in JSON. Leave it running and open a second terminal.

4. Check it's alive

bash
curl http://127.0.0.1:8787/health
json
{"status":"ok","service":"mcpg","version":"1.0.0-rc.17"}

A 200 with "status":"ok" means the gateway is up and serving.

The MCP endpoint at /mcp speaks the streamable-HTTP transport, which requires the full session lifecycle (initializenotifications/initialized → your calls, all carrying the mcp-session-id header the server returns and an accept: application/json, text/event-stream header). A raw curl of tools/list will be rejected with missing mcp-session-id header — use a real MCP client to drive it (next step).

5. Point a client at it

Any MCP client connects at http://127.0.0.1:8787/mcp and handles the lifecycle for you:

  • Claude Desktop / Cursor / Continue — add an MCP server with url: http://127.0.0.1:8787/mcp. You'll see dev.mock.echo and dev.http.get in its tool list — proof both bindings wired up end-to-end.
  • MCP Inspector (npx @modelcontextprotocol/inspector) — connect to the same URL to browse tools/prompts/resources interactively.

What's next

dev.http.get already calls a real endpoint. To go further, declare the plugin for the backend you need and add a binding against it:

  • Configuration reference — every key, including MCPG's 32 backend plugins (http, sql, openapi, the LLM backends, and more).
  • Identity guide — wire up OIDC, mTLS, SPIFFE, or API keys before you leave loopback.
  • Policy guide — authorize tool calls with Cedar, OPA, or Casbin.
  • Kubernetes install — take it to production with the operator and a Helm chart.