MCP character catalog
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP character catalogShow me all Rebel Alliance characters"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP character catalog
An educational Python MCP server with four bundled character records and two
read-only tools. The official MCP SDK serves Streamable HTTP at /mcp; /health
is anonymous and returns {"status":"ok"}. There is no model or external catalog.
The hosted app uses Entra-backed OAuth with Dynamic discovery. FastMCP's
maintained OAuthProxy supplies registration, browser consent and S256 PKCE;
the official SDK still serves the tools. Broker tokens reference encrypted
upstream Entra tokens, whose signature, tenant, API audience, lifetime and
delegated Catalog.Read scope are also verified. API keys and raw Entra tokens
cannot bypass broker authentication.
Project layout
catalog/: tools, configuration, authentication and safe JSON logging.infra/,azure.yaml,scripts/deploy.py: Azure deployment.tests/,.github/workflows/checks.yml: regression tests and CI.Editable workshop diagram: agenda and architecture.
Related MCP server: d365-bc-mcp
Develop and test
Use Python 3.14 (tested; supported range 3.12-3.14). No Docker or Azure account is needed for local tests.
python3 -m venv .venv
. .venv/bin/activate
python -m pip install --require-hashes -r requirements.txt -r requirements-dev.txt
pytest -q
ruff check .
ruff format --check .For an offline development server, use the existing API-key mode:
export MCP_AUTH_MODE=api_key
export MCP_ALLOWED_HOSTS=localhost,127.0.0.1
export MCP_API_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
python -m uvicorn catalog.server:create_app --factory \
--host 127.0.0.1 --port 8000 --no-access-logClients must send that key in X-API-Key; query-string keys are not accepted.
Do not paste credentials into chat or recordings. Visiting /mcp in a browser
is not an MCP test; the suite exercises actual SDK clients in modern and legacy
modes, including tool contracts and failure cases.
Tool | Behavior |
| Returns |
| Returns |
Matching is exact, case-insensitive and trims whitespace. Blank, non-string and over-100-character inputs fail; tools must not guess absent facts.
Deploy or update Azure
Cloud deployment requires approval and incurs charges. Prerequisites: Azure CLI, azd, Bicep, an approved subscription/region and permissions to create resources, run ACR builds and assign roles. Azure CLI and azd must use the same subscription. Local Docker is not required: ACR builds the Linux image remotely.
The approved environment already has two single-tenant Entra registrations:
an API exposing delegated Catalog.Read with v2 access tokens, and a confidential
upstream client permitted that scope. Their IDs are in private
.azure/entra-registration.json. Do not create duplicates or add Graph-wide
permissions. For another approved environment, create equivalent registrations.
Keep deployment settings in the existing ignored, mode-0600 .env.broker:
Setting | Value |
|
|
| Tenant UUID |
| API application/client UUID |
| Confidential upstream client UUID |
| Its credential value |
| Stable generated ASCII secret, at least 43 characters |
| Independent, stable Fernet key |
For a new environment, generate the signing key with secrets.token_urlsafe(48)
and the encryption key with cryptography.fernet.Fernet.generate_key(), storing
the results securely. Do not regenerate keys during normal deployment.
With the virtual environment active and the existing approved azd environment selected:
set -a
. ./.env.broker
set +a
azd provisionThis validates configuration, provisions infrastructure, remotely builds the
image and deploys it with secure temporary parameters. Use azd provision, not
azd deploy, for updates. Never put secrets in azd env set, command arguments,
source control or debug logs.
Broker mode creates a separate app (base app name truncated to 25 characters
plus -broker), retaining any original direct-Entra app. Use the effective name
printed by the hook; azd's base app-name output is not the broker app name:
az containerapp show --resource-group <resource-group> \
--name <broker-app-name> --query properties.configuration.ingress.fqdn -o tsvRegister https://<broker-fqdn>/auth/callback as an exact Web redirect on the
upstream Entra client, preserving other approved callbacks. Set private
MCP_URL and MCP_RESOURCE_URL to https://<broker-fqdn>/mcp, and
MCP_ALLOWED_HOSTS to its hostname. Bicep derives resource/host, Azure Tables
endpoint and managed-identity settings at deployment; private-network broker
storage is not accessible from an ordinary local development server.
Connect Copilot Studio
Use an account/environment with Copilot authoring, connection permissions, generative orchestration and tenant data-policy approval.
Open Tools > Add a tool > New tool > Model Context Protocol.
Enter the broker
/mcpURL from.env.broker, not the original direct-Entra URL. Select OAuth 2.0 > Dynamic discovery. No client ID or secret is entered.Create a connection, approve broker consent, then sign in and consent to
Catalog.Readin Entra. Tenant policy may require admin approval.Add to the agent and confirm
list_charactersandget_character. Test all characters, the two Rebels, and a nonexistent name; inspect actual tool arguments, results and error status rather than just the agent's answer.
The default broker callback allowlist covers
https://global.consent.azure-apim.net/redirect and its path descendants.
If Copilot supplies a regional callback, add that exact trusted HTTPS URI
to MCP_BROKER_REDIRECT_URIS and redeploy. Copilot callbacks go in this allowlist,
not on the upstream Entra app. Never allow arbitrary redirects.
UI labels and feature availability vary by tenant; see
Microsoft's onboarding guide.
Operations and verification
Check
/health,/.well-known/oauth-protected-resource/mcpand/.well-known/oauth-authorization-server; missing/invalid credentials at/mcpmust return 401. Hosted ingress is HTTPS-only.OAuth state is Fernet-encrypted in private-endpoint Azure Tables. Managed identity has AcrPull plus Table Data Contributor on the dedicated table; public storage and shared-key access are disabled. Storage/key-fetch outages return 503, not anonymous access. Expiry checks are not physical retention cleanup; manage retained state explicitly.
Broker mode is capped at one replica: shared storage does not make in-process refresh locks distributed. Registration is limited to 16 KiB and 60 attempts/minute/process; this is a workshop, not production abuse protection. Default minimum replicas is zero; use
MCP_MIN_REPLICAS=1when rehearsing if approved, accepting idle charges. ACR, networking, private endpoints/storage, compute and Copilot Studio can incur charges.Preserve signing/encryption keys. Rotate the upstream credential before its 90-day expiry and redeploy. Signing-key rotation requires reconnection; encryption-key rotation needs a state migration or explicitly approved reset.
Live discovery, DCR, consent-to-Entra redirects and registration persistence after replica replacement were verified. Tests simulate the delegated exchange. Actual Copilot Studio sign-in, refresh and hosted tool calls remain tenant checks, not proven by local tests. No group, per-record authorization or downstream on-behalf-of flow is implemented; connection identity behavior depends on the Copilot tool/channel configuration.
Keep ignored
.env,.env.entra,.env.brokerand.azure/private. The first two retain local/previous direct-mode settings, not the current broker setup.Cleanup requires approval: remove the dedicated Copilot connection, then use
azd downonly for the dedicated workshop environment. Entra registrations, service principals and consent are outside that resource-group cleanup.
Dependencies are declared in pyproject.toml and hash-locked separately for
runtime/development. To intentionally refresh, use uv pip compile pyproject.toml --universal --generate-hashes --no-header --no-annotate -o requirements.txt and
repeat with --group dev -o requirements-dev.txt; review and rerun checks.
License and attribution
Code, tests and documentation use the Microsoft MIT license. Dependencies retain their own licenses. The Azure Container Apps icon embedded in the editable diagram is from Microsoft's Azure Public Service Icons V24, used unchanged under Microsoft's architectural/training use terms; it is not covered by this project's MIT license. Star Wars names and minimal facts are an independently written educational fixture, not a copied dataset. This project is unofficial and has no affiliation with Microsoft, Disney or Lucasfilm. No character artwork or franchise logos are included.
This server cannot be deployed
Maintenance
Related MCP Connectors
Free Star Wars MCP server (SWAPI): people, films, planets, species, starships, vehicles. No API key.
Read-only MCP server that answers questions about turva.dev from its published data. Five tools return JSON: the service catalog with prices, contact and operator details, engagement principles and dated agent-readiness and security evidence with verification links. Connect over Streamable HTTP. You need no API key. The server does not scan other websites or run audits.
Query, browse, and automate OmegaAI workspaces from any MCP client. Streamable HTTP with OAuth 2.0.
MCP server for Argo RPG Platform — connects AI assistants to campaign data via OAuth2
Related MCP Servers
- AlicenseAqualityDmaintenanceRead-only MCP server providing AI access to verifiable web, GitHub, and local sources, plus a managed fantasy entity catalog, with strong security and provenance tracking.101MIT
- AlicenseAqualityCmaintenanceRead-only MCP server for Dynamics 365 Business Central, enabling AI clients to query live ERP data like customers, items, orders, and invoices via GET-only APIs with dual authentication and stdio/HTTP transports.10MIT
- FlicenseAqualityCmaintenanceRead-only MCP server that exposes Rick and Morty characters, locations, and episodes as tools and resources, with input validation, anti-SSRF protection, rate limiting, and output sanitization.7-
- AlicenseNot gradedqualityBmaintenanceExposes a small in-memory directory of ten people over streamable HTTP, letting an AI agent list every entry or look someone up by name or email.MIT