v2.0.1

MCP Server

This tutorial demonstrates Kavach MCP through automated tests, direct APIs, stdio, native Streamable HTTP, and MCPO.

Overview

The Kavach MCP server is a stateless transport adapter over the REST control plane. It exposes governed read and controlled-write operations to agents through the Model Context Protocol. This tutorial shows six ways to interact with it.

Level 1: Automated tests

Run the MCP test suite:

bash
uv run pytest tests/mcp

Level 2: Python API (no REST)

Use the MCP server object directly with its configured REST client. This expects KAVACH_API_URL to point to a running Kavach REST API (default: http://127.0.0.1:8000).

python
from kavach import create_mcp_server

server = create_mcp_server()

# List available tools
print([tool.name for tool in server.list_tools()])

# Call a tool
result = server.call_tool("provider.list")
print(result.model_dump())

Level 3: With REST API running

Start the REST API in one terminal:

bash
uvicorn kavach.api.app:app --reload

Then in another shell, interact with the MCP server:

python
from kavach import create_mcp_server

server = create_mcp_server()

# Provider discovery
print(server.call_tool("provider.list").model_dump())

# List jobs
print(server.call_tool("job.list", {"limit": 10}).model_dump())

# Registry lookup
print(server.call_tool("registry.list_models").model_dump())

# Evaluation history
print(server.call_tool("evaluation.history", {"execution_id": "exec-1"}).model_dump())

Level 4: JSON-RPC via stdio

Pipe line-delimited JSON-RPC messages into a tiny Python runner. This is how MCP clients communicate with the server.

List tools, no REST required:

bash
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
| uv run python -c 'from kavach import create_mcp_server; create_mcp_server().run_stdio()'

Call a tool through stdio (REST must be running):

bash
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"job.list","arguments":{"limit":10}}}' \
| KAVACH_API_URL=http://127.0.0.1:8000 uv run python -c 'from kavach import create_mcp_server; create_mcp_server().run_stdio()'

It expects one JSON-RPC message per line and writes one JSON-RPC response per line. notifications/initialized intentionally returns no output.

Level 5: Native Streamable HTTP

Use the native HTTP endpoint when an MCP-aware client runs outside the local machine or when each request needs a user identity. Start the local stack, then run the MCP service separately:

bash
# Terminal 1: Keycloak and the Kavach REST API
./kavach-local.sh

# Terminal 2: native MCP endpoint
uv run kavach-mcp --transport streamable-http --host 127.0.0.1 --port 8002

The endpoint is http://127.0.0.1:8002/mcp. Fetch a local service token and use it as the client's Authorization header:

bash
uv run python scripts/mcp/fetch-access-token.py

For a visual client, start ./scripts/mcp/start-inspector.sh, open the complete URL it prints (including its proxy token), then configure Streamable HTTP, Direct connection, the endpoint above, and Authorization: Bearer <access-token>. Leave the Inspector OAuth form empty: the bearer token is already supplied as a custom header. See the Streamable HTTP guide for the full client example and troubleshooting.

Level 6: MCPO over HTTP

MCPO wraps the stdio MCP server in an OpenAPI-compatible HTTP surface. Start it through the repository helper after Keycloak and the REST stack are running:

bash
./scripts/mcp/start-mcp.sh
open http://127.0.0.1:8001/docs

Calls made through MCPO still require the kavach-mcp service account to be a tenant member with the required role assignments. A valid token can still receive 403 when the actor lacks the corresponding permission.