v1.0.3

MCP Server

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

Overview

The 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 AI_GOVERNANCE_API_URL to point to a running AI Governance Platform REST API (default: http://127.0.0.1:8000).

python
from ai_governance 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 ai_governance.api.app:app --reload

Then in another shell, interact with the MCP server:

python
from ai_governance 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 ai_governance 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}}}' \
| AI_GOVERNANCE_API_URL=http://127.0.0.1:8000 uv run python -c 'from ai_governance 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 such as VS Code needs to act as a signed-in person. This is different from MCPO: native HTTP speaks MCP, while MCPO exposes ordinary OpenAPI routes. Start the local stack, then run the MCP service separately:

bash
# Terminal 1: Keycloak and the AI Governance Platform REST API
./servers-local.sh

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

The endpoint is http://localhost:8002/mcp. For a scripted stateless 2026-07-28 smoke test, fetch a local service token and make one self-contained tool request:

bash
( unset VIRTUAL_ENV; uv run python scripts/mcp/fetch-access-token.py )
TOKEN="$(pbpaste)"

curl -sS http://127.0.0.1:8002/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: tools/call' \
  -H 'Mcp-Name: provider_list' \
  --data '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"provider_list","arguments":{},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"manual-curl-test","version":"1.0"},"io.modelcontextprotocol/clientCapabilities":{}}}}' \
  | jq '{isError: .result.isError, status: .result.structuredContent.status}'

A successful call returns isError: false and status: ok. Noinitialize call or protocol session is required. The endpoint keeps legacy session-based support for older clients; new integrations should use this version.

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.

Quick VS Code test

Add this to .vscode/mcp.json. The explicit client ID is important: it selects the AI Governance Platform public OAuth client used by local VS Code sign-in.

json
{
  "servers": {
    "ai-governance": {
      "type": "http",
      "url": "http://localhost:8002/mcp",
      "oauth": { "clientId": "ai-governance-mcp-vscode" }
    }
  }
}

Run MCP: List Servers, start ai-governance, and complete the browser sign-in as studio. Then ask Copilot:

text
Call exactly one MCP tool: provider_list.
Do not call a write tool.
Use an empty JSON object: {}

Native HTTP uses underscore names such as provider_list andcontext_current. The direct Python and stdio examples above use the Core registry's dotted names, such as provider.list.

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 ai-governance-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.