Class: DocsKit::McpController

Inherits:
ActionController::Base
  • Object
show all
Defined in:
app/controllers/docs_kit/mcp_controller.rb

Overview

The built-in read-only MCP endpoint — one gem controller, host-drawn route (same shape as DocsKit::LlmsController/SearchController; the engine adds no routes):

# config/routes.rb
post  "/mcp" => "docs_kit/mcp#create"
match "/mcp" => "docs_kit/mcp#method_not_allowed", via: %i[get delete]

A user adds https://docs.example.com/mcp to Claude Code / Claude.ai / Cursor once and the docs become first-class agent tools (list_pages / get_page / search_docs) over the SAME registry the site renders from. See DocsKit::McpServer / DocsKit::McpTools.

Stateless JSON-RPC: each POST is independent (no SSE session), so it works behind the existing Kamal/Cloudflare deploy unchanged. #create delegates the whole protocol to DocsKit::McpServer#handle_json — the SDK parses the request, dispatches the tool, and serializes the response (including JSON-RPC errors), so the controller never hand-rolls the protocol.

OFF unless BOTH the optional mcp gem is present AND the site left c.mcp on (DocsKit.configuration#mcp_enabled?). A site without the gem, or with c.mcp = false, gets a 404 here and is byte-identical to before this feature.

Instance Method Summary collapse

Instance Method Details

#createObject



34
35
36
37
38
39
40
41
42
43
44
# File 'app/controllers/docs_kit/mcp_controller.rb', line 34

def create
  return head(:not_found) unless docs_config.mcp_enabled?

  server = DocsKit::McpServer.build(docs_config, base_url: request.base_url, view_context:)
  return head(:not_found) unless server

  # #handle_json returns an already-serialized JSON string, so render it as the
  # raw body with the JSON content type — `render json:` would re-encode the
  # string (wrapping it in quotes), corrupting the JSON-RPC envelope.
  render body: server.handle_json(request.body.read), content_type: "application/json"
end

#method_not_allowedObject

Read-only + stateless: the endpoint speaks JSON-RPC over POST only. There is no standalone SSE stream (GET) and no session to terminate (DELETE), so both are 405 rather than the SDK's session machinery.



49
50
51
# File 'app/controllers/docs_kit/mcp_controller.rb', line 49

def method_not_allowed
  head :method_not_allowed
end