Skip to main content
Glama

MCP Playground

What this is

MCP Playground is a browser-managed playground for authoring persistent mock MCP servers and OpenAI-compatible endpoints. It is purpose-built for Microsoft Copilot Studio demos, bootcamps, and solution-architecture training. Admins can model multiple mock servers, multiple endpoints, and shared demo datasets. Definitions and live demo data persist, so trainees can keep working across restarts.

Related MCP server: SimuLoom MCP

Exposed surfaces

Surface

Path

Auth

Admin UI

/ui/

session cookie

Admin CRUD API

/api/*

session cookie or API key; writes require admin scope

Mock MCP server

/mcp/{slug}

per-server (open or API key)

Management MCP server

/mcp/_admin

API key, admin scope

Plain REST mock

/mock/{slug}/*

per-server (open or API key)

OpenAI-compatible chat

POST /v1/{slug}/chat/completions

per-endpoint (open or API key)

Public recipe playbooks

/r/, /r/{slug}, /api/public/recipes

open, read-only

Health

/health

open

flowchart LR
    Trainer["๐Ÿง‘โ€๐Ÿซ Trainer<br/>browser or AI agent"]
    Attendee["๐Ÿ‘ฅ Attendees<br/>Copilot Studio / Cowork"]

    subgraph App["MCP Playground"]
        UI["Admin UI<br/>/ui/"]
        AdminAPI["Admin API<br/>/api/*"]
        AdminMCP["Management MCP<br/>/mcp/_admin โ€” 57 tools"]
        MockMCP["Mock MCP servers<br/>/mcp/{slug}"]
        MockREST["REST mocks + Swagger<br/>/mock/{slug}/*"]
        LLM["OpenAI-compatible<br/>/v1/{slug}/chat/completions"]
        Store[("SQLite on /data<br/>definitions ยท live ยท seed")]
    end

    Trainer --> UI --> AdminAPI
    Trainer --> AdminMCP --> AdminAPI
    Attendee --> MockMCP
    Attendee --> MockREST
    Attendee --> LLM

    AdminAPI --> Store
    MockMCP --> Store
    MockREST --> Store
    LLM --> Store

    classDef person fill:#deecf9,stroke:#0078d4,stroke-width:2px,color:#12232e
    classDef admin fill:#e8dff5,stroke:#742774,stroke-width:2px,color:#2b1b2b
    classDef mock fill:#dff6dd,stroke:#107c10,stroke-width:2px,color:#0b2b0b
    classDef data fill:#fff4ce,stroke:#d29200,stroke-width:2px,color:#3b2f00

    class Trainer,Attendee person
    class UI,AdminAPI,AdminMCP admin
    class MockMCP,MockREST,LLM mock
    class Store data

Purple is trainer-only and needs admin auth. Green is what attendees consume. Everything reads and writes the same SQLite file, so a change made through the UI is instantly visible over MCP, REST, and Swagger.

Quick start (local, no container)

uv sync
cp .env.example .env
uv run python main.py
curl http://localhost:2009/health

Expected response:

{"status":"ok"}

Quick start (container)

docker compose up --build

Podman equivalent:

podman compose up --build

Then verify:

curl http://localhost:2009/health

Configuration

Copy .env.example to .env and edit values for your environment.

Key

Meaning

Default

LOG_LEVEL

Loguru log level.

INFO

HOST

Host interface the FastAPI server binds to. Use 0.0.0.0 in containers.

0.0.0.0

PORT

Application port. Keep this at 2009.

2009

DB_PATH

SQLite database file path. Containers override this to /data/playground.db.

playground.db

PUBLIC_BASE_URL

Public base URL used when generating links or callback URLs.

http://localhost:2009

BOOTSTRAP_USER

Optional initial admin username. Leave blank to auto-generate credentials on first boot.

blank

BOOTSTRAP_PASSWORD

Optional initial admin password. Leave blank to auto-generate credentials on first boot.

blank

INSECURE_COOKIES

Set to 1 when serving over plain HTTP on a LAN so session cookies still work.

0

Admin UI

The admin UI at /ui/ has eleven tabs.

Tab

What it does

Catalog

Browse every server as cards with slug, auth mode, dataset/tool/row counts, and recipe count; clone one server or bulk-clone team copies.

Recipes

Manage agent playbooks with instructions, example prompts, toolsets, destinations, and public handouts.

Cohort

Bootcamp control panel for team readiness, handout export, traffic by team, and reset-to-seed.

Servers

Create and edit mock MCP servers; copy the live MCP URL for each.

Datasets

Paste or edit JSON or CSV; inspect the inferred field schema; manage seed snapshots.

Endpoints

Define MCP tools by describing REST-like endpoint shapes; tool type is inferred live.

LLM endpoints

Create OpenAI-compatible mock or proxy chat endpoints; set first-match-wins response rules.

Test console

Call an endpoint over REST (/mock/{slug}/โ€ฆ) to exercise writes and see the real HTTP status plus a copyable curl line, or through the Executor path (/api/servers/{slug}/tools/{tool_name}/call) which is admin-gated and read-only.

Traffic

Browse every recorded request and response; optionally auto-refresh every three seconds.

Connect it

Copy the exact values for the Copilot Studio MCP server dialog; also shows custom connector steps with a Swagger export link.

API keys

Create global API keys with readonly or admin scope; the plaintext key is shown once on creation.

Catalog and bootcamp cloning

The Catalog tab is the first tab in the sidebar. It shows every server in a card grid with slug, auth mode, metrics for datasets, tools, and rows, and an N recipes badge. From a card, an admin can create one clone or bulk-clone one source server into numbered team servers.

This is the bootcamp provisioning path: build one good server, then bulk-clone it once per training team.

Endpoint

Body

Result

GET /api/catalog

none

200 bare JSON list of servers with counts.

POST /api/servers/{server_id}/clone

{"slug": "...", "name": "..."} where name is optional

201 with the new server; 404 if the source is missing, 409 if the slug exists, 400 if the slug is invalid.

POST /api/servers/{server_id}/bulk-clone

{"prefix": "...", "count": N, "start": 1} where start defaults to 1

201 with {"created": [...]}; 409 if any generated slug exists; 400 if count is below 1, above 50, or a generated slug is invalid.

Bulk clone is all-or-nothing. If any target slug already exists, it creates nothing. Slugs are numbered with zero padding to the width of start + count - 1, with a minimum width of two: prefix hr-team, count 20, start 1 creates hr-team01 through hr-team20.

Clone deep-copies the server row, datasets, live dataset rows, seed dataset rows, and endpoints with remapped dataset IDs. It does not copy API keys, call log traffic, or LLM endpoints.

Bulk clone deliberately does not clone recipes. A recipe is one assignment that can be used by every team; cloning it once per generated server would create duplicate playbooks that trainers then have to maintain by hand. The public recipe page shows the tools from the template server, and trainers give attendees their team-specific server URL separately.

Recipes

A recipe is an agent playbook: a scenario-level assignment that tells a bootcamp attendee what agent to build. It contains a title, skill badge, department, summary, example prompts, copy-paste agent_instructions, a set of MCP tools, and optional informational destinations such as Outlook or Teams.

Schema version was bumped from 2 to 3 and adds two tables:

Table

Purpose

recipe

Instance-level playbook metadata: slug, title, skill, department, summary, instructions, prompts, destinations, and published state.

recipe_tool

Join table from a recipe to selected endpoint tools, including the source server for each tool.

Recipes are the deliberate exception to the rest of the schema. Everywhere else server_id is a foreign key. A recipe can span tools from multiple servers, so it is an instance-level object, not a child of one server.

The Recipes tab sits between Catalog and Cohort. It has a recipe list on the left and an editor on the right for slug, title, department, skill, summary, agent instructions, published state, example prompts, server+tool picker, and destination tags. Actions are Save, Delete, Copy public link, Open public page, and Download handout.

Admin API under /api is session-gated:

Endpoint

Result

GET /api/recipes

List recipes.

POST /api/recipes

Create a recipe.

GET /api/recipes/{recipe_id}

Read one recipe.

PATCH /api/recipes/{recipe_id}

Update one recipe.

DELETE /api/recipes/{recipe_id}

Delete one recipe.

PUT /api/recipes/{recipe_id}/tools

Replace the whole toolset in one call.

GET /api/recipes/validate

Validation report; never raises.

GET /api/recipes/departments

Distinct departments with recipe counts.

GET /api/recipes/{recipe_id}/handout

Markdown handout; add ?download=true to download.

Public surface:

Endpoint

Result

GET /r/

Public Agent Playbook index with cards filtered by skill and department.

GET /r/{slug}

Public recipe detail page.

GET /api/public/recipes

JSON used by the public pages.

This is the first unauthenticated HTML surface in the app. It is read-only: no session, no cookie, no POST, and no mutation. Only published = 1 recipes are exposed. A draft or unknown slug returns 404, not 403, so existence is not leaked. The public API never exposes API keys, password hashes, or call_log.

First boot seeds 7 published recipes:

Slug

Title

Skill

Department

order-status-assistant

Order status assistant

beginner

Sales Operations

leave-request-handling

Leave request handling

beginner

Human Resources

it-ticket-triage

IT ticket triage

intermediate

IT Operations

pipeline-review

Pipeline review

intermediate

Sales Operations

expense-approval

Expense approval

intermediate

Finance & Procurement

expense-manager-lookup

Expense + manager lookup

advanced

Finance & Procurement (cross-server)

order-problem-it-ticket

Order problem โ†’ IT ticket

advanced

Operations & Supply Chain (cross-server)

The seed set spans 5 servers, 15 datasets, 42 endpoints, and 40 recipe-to-tool links.

The management MCP server exposes nine recipe tools: list_recipes, get_recipe, create_recipe, update_recipe, delete_recipe, set_recipe_tools, validate_recipes, list_recipe_departments, and get_recipe_handout.

Theme

The UI uses a green brand palette: --brand: #16a34a in light mode and #22c55e in dark mode. The success colour --ok is teal (#0e7490) so success callouts stay distinct from the brand colour.

The header has a sun/moon toggle. The selected theme is stored in localStorage.theme and applied to <html data-theme="...">. If no explicit choice exists, the default follows prefers-color-scheme.

An inline script in <head> applies the theme before first paint, preventing a white flash on reload. @media print forces light tokens so recipe handouts print legibly.

Cohort control panel

The Cohort tab is the third tab in the sidebar. It is the bootcamp control panel for trainers.

Panel

What it does

Team servers

One row per server with slug, name, readiness status, auth mode, dataset/endpoint/row summary, call count, last call, MCP URL, and REST URL. Each URL has a Copy button. A text filter narrows the list. Ready means seeded, in sync, and no auth. Data drift means live rows differ from seed rows. Seeded API-key servers show Needs key.

Handout preview

Print-friendly `Team slug

Traffic by team

Per-server calls, OK count, error count, average duration, and last call, sorted by call count descending. A server absent from this table has not called anything yet.

Reset training environment

Destructive reset panel. Prefix filter plus Reset matching servers behind a confirm dialog. Empty prefix resets all servers. Live rows are restored from seed rows.

Set PUBLIC_BASE_URL before exporting handouts. Cohort URLs are built from PUBLIC_BASE_URL, defaulting to http://localhost:2009. If you leave the default, the handout contains localhost URLs that only work on the trainer's machine.

API keys are global, not per-server. The api_key table has no server_id column. Keys are sha256-hashed and the plaintext is shown exactly once at creation. The handout cannot contain a per-team API key. Servers with auth_mode='none' are handout-ready as-is; servers with auth_mode='api_key' need a key distributed out-of-band.

Endpoint

Result

GET /api/cohort

200 bare JSON list. Each item has id, slug, name, description, auth_mode, dataset_count, endpoint_count, row_count, seed_count, seeded, in_sync, call_count, last_call_at, mcp_url, rest_url, and swagger_url.

GET /api/traffic/summary

200 bare JSON list grouped by target_slug, with call_count, ok_count, error_count, avg_duration_ms, and last_call_at, ordered by call count descending.

POST /api/servers/reset-all-to-seed

200 reset summary. Body is optional; bodyless resets all servers. Use {"prefix": "hr-team"} to reset only matching slugs.

Multi-table datasets and relationships

Datasets stay flat JSON row collections. A relationship is metadata that links a field on one dataset to a field on another, so callers can inline related rows at query time with the expand query parameter. Relationships are declared per server on the Datasets tab.

Relationships are advisory. They do not enforce foreign keys in SQLite, they do not cascade, and they do not block writes that break a link. A missing parent resolves to null; a childless parent resolves to [].

Rules:

  • expand works on read operations only. create, update, and delete with expand return 400.

  • Depth is one level. A dotted name such as order.customer returns 400.

  • At most 5 expand names per request. Repeats are deduplicated.

  • summary_fields projection is preserved; expanded keys are merged on top of it.

  • A forward expand returns an object or null. An inverse expand returns an array.

  • expand, limit, offset, and _row_id are reserved and cannot be used as expand names.

Endpoint

Body

Result

GET /api/servers/{server_id}/relationships

none

200 list of relationships for the server.

GET /api/servers/{server_id}/relationships/validate

none

200 {"ok": bool, "relationship_count": N, "issues": [...]}. Never raises; orphan rows surface as issues.

POST /api/servers/{server_id}/relationships

{"name", "source_dataset_id", "source_field", "target_dataset_id", "target_field", "relation_type", "expand_name", "inverse_expand_name", "required", "description"}

201 with the relationship; 409 on a duplicate expand name; 400 on a cross-server dataset, a reserved name, or a bad relation type.

DELETE /api/relationships/{relationship_id}

none

204; 404 if it does not exist.

POST /api/relationships/ensure-demo

{"server_id": N} optional

200 {"servers_touched", "relationships_created", "skipped_existing"}. Idempotent.

GET /api/datasets/{dataset_id}/expands

none

200 list of available expand names with direction, returns, and the target dataset.

relation_type is many_to_one or one_to_one. Self-references are allowed. The same six operations are exposed as management MCP tools.

Example: GET /mock/contoso-orders/order-lines?expand=order inlines the parent order into every line. GET /mock/contoso-orders/orders/1001?expand=lines inlines the line array into the order.

Seeded sample servers

First boot seeds 5 servers, 15 datasets, 42 endpoints, 12 relationships, 1 mock LLM endpoint, and 7 published recipes. All five seeded servers use auth_mode='none', so they are handout-ready without a key.

Slug

Name

Datasets

Tools

Rows

contoso-orders

Contoso Orders

2

7

160

northwind-hris

Northwind HRIS

3

9

64

fabrikam-it-service

Fabrikam IT Service Desk

3

8

56

adatum-crm

Adatum Sales CRM

3

9

76

contoso-expenses

Contoso Travel Expenses

4

9

116

Dataset row totals: contoso-orders has orders 40 / order_lines 120; northwind-hris has employees 30 / time_off_requests 28 / org_units 6; fabrikam-it-service has tickets 30 / assets 18 / service_catalog 8; adatum-crm has accounts 20 / contacts 30 / opportunities 26; contoso-expenses has expense_reports 24 / expense_lines 60 / cost_centres 8 / approvals 24.

Seeded recipes span all 5 servers, all 15 datasets, all 42 endpoints, and 40 recipe-to-tool links. Two recipes are cross-server.

Calling a server over plain REST

Every server is exposed twice from the same endpoint definitions.

Surface

URL

Use it for

MCP

/mcp/{slug}

Copilot Studio MCP onboarding wizard

REST

/mock/{slug}

Custom connectors, Postman, curl, any HTTP client

The REST surface uses the endpoint's own method and path verbatim.

curl http://localhost:2009/mock/contoso-orders/orders?limit=5
curl http://localhost:2009/mock/contoso-orders/orders/1001
curl "http://localhost:2009/mock/contoso-orders/orders?status=open"
curl "http://localhost:2009/mock/contoso-orders/orders/search?q=northwind"
curl -X POST http://localhost:2009/mock/contoso-orders/orders \
  -H 'content-type: application/json' \
  -d '{"customer":"Fabrikam","status":"open","total":42}'
curl -X DELETE http://localhost:2009/mock/contoso-orders/orders/1001

Query string, JSON body and path placeholders are merged into one flat parameter set. Create returns 201, everything else returns 200.

The Test console in the admin UI calls this surface directly. Pick REST โ€” /mock/{slug} as the surface to exercise writes and see the real HTTP status plus a copyable curl line. The Executor surface is admin-gated and read-only, so it cannot test create, update or delete.

When a server's authentication is set to API key, send the key as X-API-Key: <key> or Authorization: Bearer <key>.

Importing into Power Platform as a custom connector

The Swagger export at /api/servers/{id}/swagger describes this REST surface, so it imports directly as a custom connector.

  1. Download the Swagger from the server's Connect it tab.

  2. Open Power Apps or Power Automate, go to Custom connectors.

  3. Choose New custom connector > Import an OpenAPI file.

  4. Add the connector to your agent in Copilot Studio.

See COPILOT-STUDIO.md for the full runbook covering both connection paths โ€” MCP server onboarding and Swagger-based custom connector.

Management MCP server

/mcp/_admin is a second FastMCP server that exposes 57 tools mirroring the admin REST API. It lets an LLM agent drive the entire playground โ€” create servers, clone team servers, load datasets, define endpoints, adjust LLM responses, manage recipes, and inspect traffic โ€” without a human touching the web UI.

Authentication: API key with admin scope, passed as X-API-Key: <key> or Authorization: Bearer <key>.

Everything the browser UI can do is also available as an MCP tool, with exactly three intentional exceptions: POST /api/auth/login, POST /api/auth/logout, and GET /api/auth/me. Those are browser-session-cookie endpoints and are meaningless over MCP, which has its own API key auth. tests/test_mcp_parity.py enforces this parity automatically so it cannot silently drift.

Setup

You need an API key with admin scope. Create one in the UI (API keys tab) or over the API.

1. Log in and create a key

BASE=http://localhost:2009        # or https://<your-fqdn>

curl -s -c /tmp/pg.jar -X POST "$BASE/api/auth/login" \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"<your-admin-password>"}'

curl -s -b /tmp/pg.jar -X POST "$BASE/api/keys" \
  -H 'Content-Type: application/json' \
  -d '{"label":"admin-mcp","scope":"admin"}'

The response contains the plaintext key exactly once. Copy it now โ€” only a hash is stored. scope is admin (read + write) or readonly.

2. Verify the key works

curl -s -o /dev/null -w '%{http_code}\n' -X POST "$BASE/mcp/_admin" \
  -H "X-API-Key: <your-key>" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

200 means you are in. 401 means the key is missing, wrong, or lacks admin scope. 406 means the Accept header is missing text/event-stream.

3. Point an MCP client at it

{
  "mcpServers": {
    "playground-admin": {
      "url": "https://<your-fqdn>/mcp/_admin",
      "headers": { "X-API-Key": "<your-key>" }
    }
  }
}
flowchart LR
    Agent["๐Ÿค– AI agent<br/>MCP client"]
    Key{{"API key<br/>scope: admin"}}
    Admin["/mcp/_admin<br/>57 tools"]
    Work["Create servers ยท clone for teams<br/>load datasets ยท define endpoints<br/>manage recipes ยท inspect traffic"]

    Agent -->|"X-API-Key header"| Key
    Key -->|"401 if missing or readonly"| Admin
    Admin --> Work

    classDef person fill:#deecf9,stroke:#0078d4,stroke-width:2px,color:#12232e
    classDef gate fill:#fde7e9,stroke:#a4262c,stroke-width:2px,color:#3b1114
    classDef admin fill:#e8dff5,stroke:#742774,stroke-width:2px,color:#2b1b2b
    classDef mock fill:#dff6dd,stroke:#107c10,stroke-width:2px,color:#0b2b0b

    class Agent person
    class Key gate
    class Admin admin
    class Work mock

Because every UI action has a tool equivalent, an agent can provision an entire bootcamp end to end: clone one source server into 20 team servers, seed their data, mint per-team API keys, and export the handouts โ€” without opening the browser.

Tools are grouped into nine areas:

Area

Tools

Servers

list_servers, get_server, create_server, clone_server, bulk_clone_server, get_catalog, update_server, delete_server, get_connection_info, export_swagger, export_server, import_server

Datasets

list_datasets, get_dataset, create_dataset, update_dataset, delete_dataset

Dataset rows

list_rows, replace_rows, add_rows, reset_to_seed, reset_all_to_seed, save_as_seed

Endpoints

list_endpoints, get_endpoint, create_endpoint, update_endpoint, delete_endpoint

Relationships

list_relationships, create_relationship, delete_relationship, validate_relationships, ensure_demo_relationships, list_expands

LLM endpoints

list_llm_endpoints, get_llm_endpoint, create_llm_endpoint, update_llm_endpoint, delete_llm_endpoint, set_llm_responses

Recipes

list_recipes, get_recipe, create_recipe, update_recipe, delete_recipe, set_recipe_tools, validate_recipes, list_recipe_departments, get_recipe_handout

API keys

list_api_keys, create_api_key, delete_api_key

Misc

call_tool, get_cohort, get_traffic, get_traffic_summary, clear_traffic

reset_all_to_seed requires confirm=true. Without it, the tool returns {"ok": false, "error": "set confirm=true to proceed", "would_affect": "..."} and changes nothing.

list_api_keys returns key metadata only and never exposes a secret hash. create_api_key returns the plaintext key exactly once; copy it immediately because it cannot be retrieved again. delete_api_key is destructive and requires confirm=true.

export_swagger returns the server's Swagger/OpenAPI spec and accepts an optional base_url override. export_server returns a portable JSON bundle for one server. import_server imports that bundle and can override the imported slug.

validate_recipes reports recipe issues, list_recipe_departments returns department counts, get_recipe_handout renders one recipe as Markdown, and list_expands lists the available $expand paths for a dataset.

Data & persistence

MCP Playground has three data tiers.

Definitions are the authored servers, endpoints, datasets, relationships, and recipes. They persist forever until an admin changes them.

Live data is the mutable runtime state used during a demo. It persists across restarts and is mutated by agent calls. If an agent creates an order during a demo, that order is still there tomorrow.

Seed data is an immutable snapshot. Reset to seed restores live data back to the snapshot. Save as seed promotes the current live data into the snapshot.

flowchart LR
    Def["๐Ÿ“ Definitions<br/>servers ยท endpoints ยท datasets<br/>relationships ยท recipes"]
    Live["๐Ÿ”„ Live data<br/>mutable demo rows"]
    Seed["๐Ÿ“ฆ Seed data<br/>immutable snapshot"]

    Def -.->|"shape the rows"| Live
    Live -->|"Save as seed"| Seed
    Seed -->|"Reset to seed"| Live
    Agents["๐Ÿค– Agent calls during a demo"] -->|"create ยท update ยท delete"| Live

    classDef def fill:#deecf9,stroke:#0078d4,stroke-width:2px,color:#12232e
    classDef live fill:#dff6dd,stroke:#107c10,stroke-width:2px,color:#0b2b0b
    classDef seed fill:#fff4ce,stroke:#d29200,stroke-width:2px,color:#3b2f00
    classDef ext fill:#f3f2f1,stroke:#605e5c,stroke-width:2px,color:#201f1e

    class Def def
    class Live live
    class Seed seed
    class Agents ext

All three tiers live in the same SQLite file and survive restarts. If an agent creates an order during a demo, that order is still there tomorrow โ€” until someone resets to seed.

The Compose setup uses the named Docker volume playground-data mounted at /data. That is what keeps SQLite data alive across docker compose restart, docker compose down, and later docker compose up. Deleting that volume wipes all definitions, live data, and seed data.

Deployment

Two supported targets.

Local container โ€” the quick-start path above: docker compose up --build (or podman compose up --build) exposes the app on port 2009 and persists SQLite in the playground-data volume.

Azure Container Apps โ€” scale-to-zero, under โ‚ฌ1/month, HTTPS with a stable FQDN. Full runbook in AZURE.md.

flowchart LR
    Dev["๐Ÿ’ป Local dev<br/>uv run ยท compose"]
    GH["GitHub<br/>Roelzz/mcp_playground"]
    Actions["GitHub Actions<br/>build-image.yml"]
    GHCR["ghcr.io<br/>public image"]
    Deploy["deploy.sh<br/>Bicep ยท one resource group"]
    ACA["Azure Container Apps<br/>min=0 max=1 ยท managed TLS"]
    Files[("Azure Files<br/>/data ยท SQLite")]

    Dev -->|"git push"| GH --> Actions --> GHCR
    Dev -->|"az login"| Deploy --> ACA
    GHCR -->|"image pull"| ACA
    ACA -->|"SMB mount"| Files

    classDef local fill:#deecf9,stroke:#0078d4,stroke-width:2px,color:#12232e
    classDef ci fill:#f3f2f1,stroke:#605e5c,stroke-width:2px,color:#201f1e
    classDef azure fill:#e8dff5,stroke:#742774,stroke-width:2px,color:#2b1b2b
    classDef data fill:#fff4ce,stroke:#d29200,stroke-width:2px,color:#3b2f00

    class Dev local
    class GH,Actions,GHCR ci
    class Deploy,ACA azure
    class Files data

Short version, assuming az login is done and infra/main.parameters.json is filled in:

BOOTSTRAP_PASSWORD='<pick-a-strong-password>' ./deploy.sh

Takes about three to four minutes and prints the FQDN when it finishes. Read AZURE.md first โ€” two env vars (SQLITE_JOURNAL_MODE=DELETE and SQLITE_VFS=unix-dotfile) are mandatory on Azure Files, and teardown.sh permanently changes the URL.

Development

uv run pytest -q
uv run ruff check .
uv run ruff format .

Network note: blocked PyPI downloads

The project uses the public PyPI index. On some corporate networks โ€” including any machine behind Microsoft Entra Global Secure Access โ€” files.pythonhosted.org is blocked by web filtering, so pypi.org resolves but package downloads fail. The block applies inside containers too.

If you hit that, redirect UV to a mirror locally โ€” never commit the mirror as project config.

Host-side dependency resolution (uv lock):

export UV_DEFAULT_INDEX=https://<your-mirror>/simple

Container build. uv sync --frozen uses the absolute artefact URLs recorded in uv.lock, so UV_DEFAULT_INDEX alone is not enough โ€” rewrite the lock, build, restore:

sed -i '' -e 's|https://files.pythonhosted.org/packages|https://<your-mirror>/packages|g' \
          -e 's|https://pypi.org/simple|https://<your-mirror>/simple|g' uv.lock
podman build -t mcp-playground .
git checkout uv.lock

uv.lock records sha256 hashes alongside every URL. A mirror that copies the pythonhosted path layout serves identical artefacts, so the hashes still verify and the rewrite is safe.

For a production or Microsoft-shop deployment, use an Azure Artifacts feed with a PyPI upstream instead of a public mirror.

Roadmap

Azure deployment shipped โ€” see AZURE.md. Nothing is currently blocking a bootcamp.

Untested rather than broken, worth knowing before a large session:

  • No load test against a full 200-attendee cohort yet.

  • SQLite lock behaviour after a hard container kill (not a graceful restart) is unverified.

F
license - not found
Not graded
quality - not tested
B
maintenance

Maintenance

โ€“Maintainers
โ€“Response time
โ€“Release cycle
โ€“Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Contract-driven service virtualization and synthetic test-data management server that enables simulating APIs from OpenAPI contracts through MCP tools.
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    A universal MCP server for registering internal, external, and OpenAPI-based APIs as MCP tools. It exposes them to MCP clients via Streamable HTTP and provides admin portal, RBAC/session auth, credential injection, and audit logging.
  • A
    license
    Not graded
    quality
    B
    maintenance
    This MCP server provides a stateful, resettable, verifiable API runtime that gates every tool call, enabling agents to run long workflows against provider-shaped environments without live provider write access. It records decisions, side effects, and outcome evidence for replayable, verifiable benchmark runs.
    Apache 2.0

View all related MCP servers

Related MCP Connectors

  • Hosted MCP endpoint with realistic fake data for prototyping agents. 12 tools, no setup.

  • MCP server for AI access to Swagger by SmartBear.

  • Hosted MCP server for LLM cost estimation, model comparison, and budget-aware routing.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Roelzz/mcp_playground'

If you have feedback or need assistance with the MCP directory API, please join our Discord server