Table of Contents

Transport Modes

PoshMcp supports two transport modes for different deployment scenarios. The production implementation uses ModelContextProtocol and ModelContextProtocol.AspNetCore 1.4.1 and targets MCP 2025-11-25.

Stdio Mode

Best for: Local development, GitHub Copilot integration, single-connection scenarios.

Characteristics:

  • Single persistent connection
  • Stream-based communication
  • One runspace per connection
  • Minimal overhead

Start:

poshmcp serve --transport stdio

Configure in MCP client:

{
  "mcpServers": {
    "poshmcp": {
      "command": "poshmcp",
      "args": ["serve", "--transport", "stdio"]
    }
  }
}

HTTP Mode

Best for: Multi-user deployments, web integration, cloud infrastructure.

Characteristics:

  • MCP Streamable HTTP (2025-11-25)
  • Per-user isolation
  • Horizontal scaling capable
  • Built-in health checks

Start:

poshmcp serve --transport http --port 8080

MCP Endpoint and Protocol

The default Streamable HTTP endpoint is /; /mcp is also available as a compatibility alias. For a production deployment, set a dedicated endpoint with --mcp-path /mcp (or POSHMCP_MCP_PATH=/mcp) and publish only that endpoint through the reverse proxy or ingress.

Clients initialize with a JSON-RPC POST containing protocolVersion: "2025-11-25" and Accept: application/json, text/event-stream. The response provides Mcp-Session-Id; 2025-11-25 clients must send that header and the negotiated MCP-Protocol-Version header on all subsequent POST, GET, and DELETE requests. Responses may be JSON or Server-Sent Events, according to the client's Accept header.

# Initialize a Streamable HTTP session.
curl -i https://poshmcp.example/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"example","version":"1.0"}}}'

# Open the optional server-to-client event stream with the negotiated headers.
curl -N https://poshmcp.example/mcp \
  -H "Accept: text/event-stream" \
  -H "Mcp-Session-Id: <session-id>" \
  -H "MCP-Protocol-Version: 2025-11-25"

# Explicitly end the session.
curl -X DELETE https://poshmcp.example/mcp \
  -H "Mcp-Session-Id: <session-id>" \
  -H "MCP-Protocol-Version: 2025-11-25"

The server returns 400 for a missing, invalid, or unsupported negotiated protocol version. DELETE returns 200 for a live session; requests made after deletion or idle expiry return 404 and the client must initialize a new session. McpServer:IdleSessionTimeoutSeconds controls expiry (60 seconds by default); the SDK checks expired sessions in the background approximately every five seconds.

2024-11-05 Streamable HTTP clients remain supported for compatibility and may omit the protocol-version header after initialization. The deprecated HTTP-with-SSE transport is disabled by default. Enable it only for a required legacy-client transition:

{
  "McpServer": {
    "EnableLegacySse": true
  }
}

Deployment Security

When an Origin header is present on an MCP request, PoshMcp accepts only a same-origin request or a value in Authentication:Cors:AllowedOrigins; other origins receive 403. Configure exact HTTPS origins for browser clients rather than using a wildcard. Non-browser clients normally omit Origin.

Enable Authentication:Enabled for external deployments. MCP endpoints then require the configured McpAccess policy; /health and /health/ready remain anonymous for platform probes. See Authentication for Entra ID and API-key setup.

Health probes remain separate from the MCP endpoint:

curl https://poshmcp.example/health
curl https://poshmcp.example/health/ready

Override via Environment Variable

export POSHMCP_TRANSPORT=http
poshmcp serve