Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Mock Server

БесплатноНе проверен

A test MCP server that validates gateway connectivity, identity propagation, and provides mock tools for testing purposes.

GitHubEmbed

Описание

A test MCP server that validates gateway connectivity, identity propagation, and provides mock tools for testing purposes.

README

A test MCP server that runs behind mcp-auth-gateway. It exists to validate the platform plumbing — not to be a real product.

Purpose

This server is used to verify:

  1. gateway → backend MCP server connectivity
  2. path-based /mock/mcp routing
  3. gateway-signed X-MCP-Identity verification
  4. propagation of the user loginid
  5. the Streamable HTTP MCP transport
  6. GitOps / Kubernetes deployment

How it fits in

client ──TLS──> mcp-auth-gateway ──/mock/mcp──> mock-mcp-server (this repo)
                (Keycloak / OAuth,              (verifies X-MCP-Identity,
                 mints X-MCP-Identity)           runs MCP tools)
  • It runs only behind the gateway. External clients reach it exclusively via https://gateway.mcp.aidev.samsungds.net/mock/mcp.
  • It does NOT do Keycloak / OAuth verification itself. All external auth is the gateway's job.
  • It DOES verify the gateway's internal X-MCP-Identity JWT on /mcp and every slash-delimited path below it, rejecting anything missing or invalid with 401.
  • Tools read the caller's identity — especially loginid — through a shared get_current_user() helper; they never parse HTTP headers directly.

Identity: X-MCP-Identity

The gateway injects a signed internal JWT:

X-MCP-Identity: <gateway-signed-internal-jwt>

Example payload:

{
  "iss": "mcp-auth-gateway",
  "aud": "mock-mcp-server",
  "sub": "keycloak-user-sub",
  "loginid": "user.loginid",
  "username": "user.name",
  "email": "[email protected]",
  "groups": ["engineering"],
  "scopes": ["mcp:mock:use"],
  "request_id": "01J...",
  "iat": 1730000000,
  "nbf": 1730000000,
  "exp": 1730000060
}

Verified on every /mcp request:

  • JWT signature
  • iss == mcp-auth-gateway
  • aud == mock-mcp-server
  • integer iat, nbf, and exp, with five seconds of clock skew
  • exp > iat, exp >= nbf, and a maximum lifetime of five minutes
  • canonical, non-empty sub, loginid, and optional scalar/list values
  • exactly one non-empty X-MCP-Identity header (duplicates and combined values are rejected)

The MVP uses shared-secret HS256 via MCP_IDENTITY_JWT_SECRET; the secret must contain at least 32 bytes. The verifier lives behind a small abstraction (identity.IdentityVerifier) so a production RS256 / JWKS implementation can be dropped in without touching tools or middleware.

loginid usage

loginid is the primary per-user key. Tools use it to build deterministic, user-scoped mock data (mock_profile, mock_search) and to echo the caller's identity (echo, whoami).

Endpoints

Method Path Auth Purpose
GET /healthz none liveness
GET /readyz none readiness
ANY /mcp[/...] X-MCP-Identity (JWT) Streamable HTTP MCP endpoint

Requests to /mcp or /mcp/... without a valid X-MCP-Identity are rejected at the HTTP layer with 401 Unauthorized before reaching any tool. Similar names such as /mcpish are not part of this authentication boundary.

MCP tools

Tool Input Returns
whoami full identity asserted by the gateway
echo message: str { loginid, message }
mock_profile deterministic mock profile derived from loginid
mock_search query: str deterministic, user-scoped mock search results

Configuration

All configuration is via environment variables.

Variable Default Notes
APP_HOST 0.0.0.0
APP_PORT 8080 container port
MCP_ENDPOINT /mcp Streamable HTTP path
MCP_IDENTITY_ISSUER mcp-auth-gateway required iss
MCP_IDENTITY_AUDIENCE mock-mcp-server required aud
MCP_IDENTITY_ALGORITHM HS256 verifier algorithm
MCP_IDENTITY_JWT_SECRET required, at least 32 bytes unless dev mode is on
MCP_IDENTITY_DEV_MODE false if true, unauthenticated calls get a dummy user
LOG_LEVEL info
  • MCP_IDENTITY_JWT_SECRET is mandatory in production; the server refuses to start if it is missing or shorter than 32 bytes.
  • MCP_IDENTITY_DEV_MODE=true is only for local development. It defaults to false and must never be enabled in the cluster.

Local development

Requirements: Python ≥ 3.11 and uv.

# 1. install
uv sync --locked --extra dev

# 2. run the server
export MCP_IDENTITY_JWT_SECRET=dev-only-secret-that-is-at-least-32-bytes
export MCP_IDENTITY_DEV_MODE=false
python -m mock_mcp_server.main

Generate a dev identity token

Without the gateway you must supply your own X-MCP-Identity JWT:

export MCP_IDENTITY_JWT_SECRET=dev-only-secret-that-is-at-least-32-bytes

python scripts/make-dev-identity-token.py \
  --loginid test.user \
  --subject test-sub \
  --aud mock-mcp-server
# ->  export X_MCP_IDENTITY='<jwt>'

eval "$(python scripts/make-dev-identity-token.py --loginid test.user --subject test-sub)"

Test with curl

/mcp speaks Streamable HTTP (JSON-RPC). In stateless JSON mode you can call a tool directly:

# health (no auth)
curl -s localhost:8080/healthz

# whoami (requires identity)
curl -s localhost:8080/mcp \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -H "X-MCP-Identity: ${X_MCP_IDENTITY}" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"whoami","arguments":{}}}'

# missing identity -> 401
curl -i -s localhost:8080/mcp \
  -H "Accept: application/json, text/event-stream" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Test with MCP Inspector

Use the integrated gateway/Keycloak workflow from the sibling GitOps repository rather than connecting Inspector directly to this internal backend:

cd ../mcp-platform-gitops
scripts/local-build-push.sh
scripts/local-up.sh
scripts/local-inspector.sh

The launcher pins @modelcontextprotocol/[email protected]. In its OAuth settings use client ID mcp-inspector, no client secret, scope openid mcp:mock:use, and the preselected Streamable HTTP gateway URL http://gateway.localhost:8080/mock/mcp.

Run the tests

uv run pytest        # or: .venv/bin/python -m pytest

Docker

Image name (pushed to cr.aidev.samsungds.net/mcp-platform):

cr.aidev.samsungds.net/mcp-platform/mock-mcp-server:<commit-sha>

Build & push:

REGISTRY=cr.aidev.samsungds.net \
IMAGE_TAG="$(git rev-parse HEAD)" \
CA_CERT_FILE=/path/to/system-ca.pem \
PUSH=1 \
scripts/build-and-push.sh

The image installs production dependencies from the checked-in uv.lock with frozen semantics, runs as a non-root user, exposes 8080, and ships a HEALTHCHECK against /readyz. Tag images by commit SHA (no latest in the cluster) so GitOps pins an immutable deployment reference.

Deployment (mcp-platform-gitops)

Full Kubernetes / GitOps manifests live in mcp-platform-gitops, not here. This repo only ships the app and image. The gitops repo should deploy it as a ClusterIP Service with these values:

Setting Value
Namespace mcp-gateway
Service name mock-mcp-server
Service type ClusterIP
Container port 8080
Internal DNS http://mock-mcp-server.mcp-gateway.svc.cluster.local:8080
Internal MCP URL http://mock-mcp-server.mcp-gateway.svc.cluster.local:8080/mcp
External MCP URL https://gateway.mcp.aidev.samsungds.net/mock/mcp (gateway)

Required Secret (mcp-internal-signing, key jwt-secret) holds the shared HS256 secret, which must match the gateway's signing secret and contain at least 32 bytes.

Container env:

env:
  - name: MCP_IDENTITY_JWT_SECRET
    valueFrom:
      secretKeyRef:
        name: mcp-internal-signing
        key: jwt-secret
  - name: MCP_IDENTITY_ISSUER
    value: mcp-auth-gateway
  - name: MCP_IDENTITY_AUDIENCE
    value: mock-mcp-server

Probes: GET /healthz (liveness), GET /readyz (readiness), both on 8080.

Do NOT create a public Ingress

This service must never be exposed with its own public Ingress / LoadBalancer.

  • It performs no external authentication (no Keycloak, no OAuth). It only trusts the gateway-signed X-MCP-Identity. A direct public route would let anyone reach /mcp while bypassing the gateway's real authentication.
  • All external access must go through the gateway, which authenticates the user, mints X-MCP-Identity, and routes /mock/mcp to this ClusterIP Service.

The only external entry point is:

https://gateway.mcp.aidev.samsungds.net/mock/mcp

Project layout

src/mock_mcp_server/
  __init__.py
  main.py          # ASGI app factory + uvicorn entrypoint
  settings.py      # env-based configuration (fails fast)
  identity.py      # X-MCP-Identity JWT verification (HS256; RS256-ready)
  middleware.py    # pure-ASGI identity enforcement (401) + scope injection
  context.py       # McpUserContext + get_current_user()
  tools.py         # whoami / echo / mock_profile / mock_search
scripts/
  make-dev-identity-token.py
tests/

from github.com/wontaeJeong/mock-mcp-server

Установка Mock Server

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/wontaeJeong/mock-mcp-server

FAQ

Mock Server MCP бесплатный?

Да, Mock Server MCP бесплатный — установка в пару кликов через Unyly без оплаты.

Нужен ли API-ключ для Mock Server?

Нет, Mock Server работает без API-ключей и переменных окружения.

Mock Server — hosted или self-hosted?

Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.

Как установить Mock Server в Claude Desktop, Claude Code или Cursor?

Открой Mock Server на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.

Похожие MCP

Compare Mock Server with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории development