WebMCP
Easy8 can expose its MCP tool catalog to AI agents running directly in the user's browser through the WebMCP API.
When WebMCP is enabled, every Easy8 page registers the MCP tools with the browser via document.modelContext.registerTool() (with a fallback to the legacy navigator.modelContext surface). Browser-based AI agents can then discover and call Easy8 tools on the current page without any extra setup.
Browser support
WebMCP is an early web standard. At the time of writing it is implemented only in Chromium-based browsers behind a flag (Google Chrome 146 and newer; see Chrome's WebMCP documentation for the current flag, for example chrome://flags/#enable-webmcp-testing or the command-line switch --enable-features=WebMCP). Browsers without the API pay no cost beyond a feature check; nothing is registered and no request is made.
Relationship to the MCP server
WebMCP is a browser transport for the same tool catalog as the MCP server. Both share EasyMcp::ToolRegistry:
- Tool names, descriptions, input schemas, and annotations are identical to the
tools/listresult on/mcp. - Tool execution goes through the same
EasyMcp::ToolCallHandler, so results have the same shape astools/callresults. - Tools registered or extended by plugins through
EasyMcp::ToolRegistry.register,extend_tool, orEasyMcp::ToolExtensionsappear in WebMCP automatically. See Extending tools; no WebMCP-specific registration exists or is needed.
The differences are authentication and transport:
- The
/mcpendpoint uses API key or OAuth2 authentication and JSON-RPC. See Authentication. - WebMCP uses the logged-in browser session. Tools act as the current user, with the same visibility and permission rules as the rest of the application.
mealways resolves to the logged-in user.
How to enable WebMCP
WebMCP is disabled by default and is independent of the Enable MCP setting.
To enable it:
- Open Easy8 administration.
- Go to
Settings. - Open the
AItab. - Enable
Enable WebMCP. - Save the settings.
When WebMCP is disabled, the endpoints below return 404 Not Found and no tools are registered in the browser.
Endpoints
WebMCP uses two plain JSON endpoints instead of JSON-RPC. Both require a logged-in session; the tool_calls endpoint additionally requires the Rails CSRF token (X-CSRF-Token header) and a Content-Type: application/json body.
Requests without a logged-in session, including sessions that expired or were logged out in another tab, return 403 Forbidden with an error object. This also applies on installations that use SSO or an external identity provider; the endpoints never redirect to a login page. A session whose user must first change the password or activate two-factor authentication gets 403 Forbidden as well, with the corresponding message.
GET /web_mcp/tools
Returns the tool catalog:
{
"tools": [
{
"name": "easy8_issues_list",
"description": "Discover and triage visible tasks/issues...",
"inputSchema": { "type": "object", "properties": {} },
"annotations": { "readOnlyHint": true, "openWorldHint": false }
}
]
}
The array is exactly the result.tools value of the MCP tools/list method. See Protocol.
The catalog is cached for 5 minutes: on the server (Rails.cache, one entry per installation) and in the browser (Cache-Control: private, max-age=300), with an ETag for conditional requests (304 Not Modified). Tool availability (available_if) is therefore re-evaluated for the catalog at most every 5 minutes; a newly installed plugin or a changed feature setting shows up in the browser within about 10 minutes. Tool execution is never cached, see below.
POST /web_mcp/tool_calls
Executes one tool:
The response is the MCP tool call result (the result value of a JSON-RPC tools/call response):
The args and input aliases and flat top-level arguments accepted by /mcp tools/call work here as well. Tool availability and the user's permissions are evaluated on every call, exactly as for /mcp.
Invalid requests return 400 Bad Request with a JSON-RPC style error object: -32700 for an unparseable body, -32600 for a body that is not a JSON object or does not use Content-Type: application/json, and -32602 for invalid arguments, for example {"error": {"code": -32602, "message": "Invalid params"}}. An unknown tool returns a regular tool result with isError: true. A missing or stale CSRF token returns 422 with an error object and does not terminate the session.
WebMCP requests, including rejected ones, are logged to log/mcp.log with transport=web plus error_code/error_class fields on failures. The individual tool executions are logged to the same file by the shared MCP tool call handler, in the same format as /mcp tool calls.
Browser registration
The frontend module app/frontend/src/web_mcp/ runs on every page load from the application entrypoint:
- It checks the
enable_web_mcpflag exposed throughwindow.easySettingsand that the current user is logged in, so pages make no WebMCP request while the setting is disabled or for anonymous visitors. The initialization is queued throughEASY.schedule.late, i.e. it runs after the page's own initialization functions. - It feature-detects the WebMCP API (
document.modelContext, falling back tonavigator.modelContext). - It fetches
GET /web_mcp/toolsand registers each tool withregisterTool(), passing anAbortControllersignal that unregisters the tools when the page is really unloaded (not when it enters the back/forward cache). On the legacy surface withoutregisterTool(), it usesprovideContext()instead. - Each tool's
executecallback posts to/web_mcp/tool_callsand returns the MCP tool result to the agent. The per-execution abort signal is forwarded to the HTTP request. Tool call failures are reported to the agent as a tool result withisError: true; a failed initialization or rejected tool registrations are logged to the browser console as a warning.
Security notes
- Tools run with the permissions of the logged-in user; nothing is elevated. Write tools perform the same permission and validation checks as the MCP server and the regular UI.
- The read-only API key restriction does not apply to WebMCP because no API key is involved; browser sessions are full sessions. Enabling WebMCP therefore exposes every registered tool, including the write tools, to any agent operating in the user's browser.
- Browser agents read the page content. Descriptions, comments, wiki pages, and other user-generated content are untrusted input for such an agent (prompt injection). Enable WebMCP only for installations where this risk is acceptable, and prefer browser agents that confirm tool calls that are not marked
readOnlyHint. - The
tool_callsendpoint always verifies the Rails CSRF token. Theapi_request?exemption that the REST API uses for?format=json/.jsonrequests (and/mcpfor its JSON-RPC action) does not apply here, and a format suffix on the URL is not routable. Together with the defaultSameSite=Laxsession cookie this prevents third-party pages from calling tools with the user's session. - Tool availability (
available_if) is evaluated on the server for every tool call, exactly as for/mcp.