Deploy an MCP server¶
By the end of this tutorial you will have an MCP server running in your project,
exposing tools to an AI client, with a NetworkPolicy that constrains exactly what those
tools can reach.
Prefer clicking through the console instead? See the console walkthrough.
Scaffold status
The step structure below is agreed and stable. Exact commands, manifests and captured output are added as this flow is verified end to end on the live platform — this page deliberately shows no invented output.
Prerequisites¶
- A project and CLI access — see Get started
- An MCP server image, or one from the marketplace
- The internal system your tools will talk to — a database, an API — reachable from the cluster
Overview¶
flowchart LR
AGENT["Agent / LLM client"] -->|MCP| SRV["MCP server"]
SRV --> DB[("Internal database")]
SRV -.->|denied| NET(["Everything else"])
The MCP server is the component holding the credential. The model gets tool results; it never gets the secret.
Steps¶
1. Create a project for the server¶
Its own namespace, so its credentials and its network policy are scoped to it alone.
2. Store the tool credentials as Secrets¶
Database passwords, API tokens — mounted or injected at runtime.
3. Deploy the server¶
A Deployment and a Service. Nothing platform-specific: it is an ordinary workload.
4. Apply a default-deny egress policy¶
Then allow exactly the systems the tools need, plus DNS. See Networking for the pattern.
5. Expose it to your clients¶
Internal-only via a Service if the agent runs in-cluster; a TLS route if it does not.
6. Connect a client¶
Point your MCP-capable client at the server and confirm it discovers the tool list.
Verify¶
- The client lists the tools you expect
- A tool call returns real data from the backing system
- An egress attempt to something outside the allow-list is refused:
oc exec deploy/<mcp-server> -n <project> -- \
curl -sS --max-time 5 https://example.com || echo "blocked as expected"
Tool arguments are model output
Arguments arriving in a tool call are steered by whatever the model has read, including content from untrusted sources. Validate them server-side, use parameterised queries, and never interpolate them into a shell command.
Clean up¶
Remove everything this tutorial created, in reverse order: