MCP Profile
The mcp-profile contract validates that a Stemix IDP stack correctly exposes its capabilities
through the Model Context Protocol (MCP). MCP is a first-class
interface layer in Stemix alongside REST, CLI, and UI — it lets AI agents interact with the portal
without knowing its HTTP conventions.
Why it exists
The IDP design principle "AI over MCP-First" means every capability should be reachable by an AI agent through a stable, discoverable protocol. The MCP profile enforces that a conforming MCP server can initialize, enumerate its tools, and invoke them correctly. It does not test AI reasoning — it tests the adapter layer that connects AI agents to the portal's capabilities.
Who must pass it
Only stacks that declare both "mcp-profile" in contractProfiles and
capabilities.mcp.enabled = true in their stack.json are required to pass this profile.
The profile is skipped automatically when either declaration is absent.
Layer 1 spec
Source: tests/features/mcp-profile.feature
Scenarios (8 total)
MCP server responds to initialize with server info and capabilities
Precondition: The MCP server is running at IDP_MCP_URL (default: http://localhost:8080).
Assertions:
- MCP
initializerequest returns HTTP 2xx - JSON-RPC response contains a
resultfield result.serverInfohas a non-emptynameandversionresult.capabilitiesis present
tools/list returns the required tools with valid schemas
Precondition: The MCP server is running.
Assertions:
tools/listreturns HTTP 2xxresult.toolsis a non-empty array- Each tool has a non-empty
name,description, and aninputSchemaobject - The list includes
get_portal_summary - The list includes
check_health - The list includes
list_flow_insights - The list includes
get_flow_insight - The list includes
list_my_blockers - The list includes
list_service_risk_signals
tools/call get_portal_summary returns a portal status result
Precondition: The MCP server is running and can reach the BFF at OUR_IDP_BFF_URL.
Assertions:
tools/call get_portal_summaryreturns HTTP 2xxresult.content[0].typeis"text"result.content[0].textis valid JSON matching the shared portal summary status contract
tools/call check_health returns BFF health and readiness
Precondition: The MCP server is running and can reach the BFF at OUR_IDP_BFF_URL.
Assertions:
tools/call check_healthreturns HTTP 2xxresult.content[0].typeis"text"result.content[0].textis valid JSON withhealthandreadinessfieldshealth.statusis present
tools/call list_flow_insights returns insight list payload
Precondition: The MCP server is running and can reach the BFF at OUR_IDP_BFF_URL.
Assertions:
tools/call list_flow_insightsreturns HTTP 2xxresult.content[0].textparses to JSON withgeneratedAt,total, and aninsightsarray- At least one insight is returned
tools/call get_flow_insight returns detailed payload
Precondition: The MCP server is running and can reach the BFF at OUR_IDP_BFF_URL.
Assertions:
tools/call get_flow_insightreturns HTTP 2xxresult.content[0].textparses to JSON with aninsightobjectinsight.insightIdmatches the requested ID- Optional
explanationandrecommendedNextActionfields are strings when present
tools/call list_my_blockers filters blocker signals for an actor
Precondition: The MCP server is running and can reach the BFF at OUR_IDP_BFF_URL.
Assertions:
tools/call list_my_blockersreturns HTTP 2xx- Response JSON contains only blocker signal IDs:
blocked_on_review,waiting_on_evidence, oraging_implementation - At least one returned insight includes the requested actor in
actors
tools/call list_service_risk_signals returns risk aggregation signals
Precondition: The MCP server is running and can reach the BFF at OUR_IDP_BFF_URL.
Assertions:
tools/call list_service_risk_signalsreturns HTTP 2xx- Response JSON contains only
risk_aggregationsignals - Each returned insight includes the requested
servicein itsservicesarray
Layer 2 harness
Source: tests/src/profiles/mcp-profile.ts
The harness sends raw JSON-RPC 2.0 POST requests to IDP_MCP_URL/mcp using the existing
zero-dependency HTTP client. It handles both application/json and text/event-stream (SSE)
response formats, sends the required notifications/initialized follow-up request, and reuses
any Mcp-Session-Id header returned by the server during initialization.
Stack declarations
Stacks that expose an MCP server must declare both the profile and the capability flag:
{
"contractProfiles": ["mcp-profile"],
"capabilities": {
"mcp": { "enabled": true }
}
}
Environment variables
| Variable | Default | Description |
|---|---|---|
IDP_MCP_URL | http://localhost:8080 | Base URL for the MCP server |
OUR_IDP_BFF_URL | http://localhost:8000 | BFF URL the MCP server connects to |
Running the profile
# Start the BFF for a stack, then the MCP server, then run contract tests:
IDP_MCP_URL=http://localhost:8080 \
OUR_IDP_BFF_URL=http://localhost:8000 \
IDP_STACK_PATH=tools/mcp \
pnpm run test:contract
Related
- Contract Test Harness — Full harness guide
- Core Profile — Baseline HTTP surface
- ADR-0005 — Capability contract and conformance profiles
- ADR-0009 — Gherkin as Layer 1 format