Skip to content

MCP Protocol

The Easy8 MCP server is exposed through /mcp and currently supports the MCP methods listed below.

HTTP behaviour summary

  • GET /mcp returns 405 Method Not Allowed when MCP is enabled
  • GET /mcp returns 404 Not Found when MCP is disabled
  • POST /mcp returns 404 Not Found when MCP is disabled
  • JSON-RPC batch arrays are not supported; send one request object per HTTP call
  • notifications without id return empty responses with 202 Accepted or 204 No Content depending on the method

initialize

Initializes the MCP session and returns server metadata, protocol version, and declared capabilities.

The response also includes the MCP-Protocol-Version HTTP header.

Example request:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize"
}

Example response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-11-25",
    "capabilities": {
      "tools": {
        "listChanged": false
      }
    },
    "serverInfo": {
      "name": "easy8-mcp",
      "title": "Easy8 MCP",
      "version": "0.1.0",
      "description": "Easy8 MCP server",
      "icons": [
        {
          "src": "https://your-easy8.example.com/packs/logo--mark.svg",
          "mimeType": "image/svg+xml",
          "sizes": ["any"]
        },
        {
          "src": "https://your-easy8.example.com/packs/favicon.ico",
          "mimeType": "image/x-icon",
          "sizes": ["48x48"]
        }
      ]
    }
  }
}

ping

Simple health-style method. Returns an empty result.

tools/list

Returns the list of available MCP tools together with their JSON schemas.

Use this to discover the tool catalog dynamically.

Tools are published through EasyMcp::ToolRegistry. The registry lists only tools whose service class can be resolved and whose availability predicate passes. Core tool names use easy8_<resource>_<verb>. Plugin-owned tools should use easy8_<plugin_domain>_<resource>_<verb> and register themselves from the owning plugin.

Each tool definition includes MCP safety annotations. Read-only tools publish readOnlyHint: true. Write tools publish readOnlyHint: false, destructiveHint, and idempotentHint: false. These annotations help MCP clients distinguish discovery/read operations from actions that can mutate Easy8 data. Runtime permissions are still enforced by Easy8 authorization and read-only API keys.

tools/call

Calls one of the available Easy8 tools.

Use name and arguments. args and input are accepted for compatibility.

Example:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "easy8_issues_get",
    "arguments": {
      "id": 123
    }
  }
}

Tool responses keep their JSON payload or metadata in the first MCP text block, result.content[0].text. Successful calls set isError to false; business errors set isError to true. A successful response may also contain separate non-text content blocks, so clients must not assume that every item in result.content is text.

Attachment image content

For easy8_issue_attachments_read with content_format: "auto" (the default), an attachment detected as image/* from its bytes using Marcel returns JSON metadata in result.content[0].text, followed by a separate standard MCP image block in result.content[1]:

  • type: "image"
  • data: base64 encoding of the complete original image bytes
  • mimeType: the MIME type detected from those bytes

The image block is a sibling of the text block, not JSON serialized inside content[0].text. Base64 is encoded once into the image block's data field; it is not duplicated in the metadata text or wrapped in a data URL.

Illustrative response with synthetic IDs and a complete, originally 1-by-1 GIF. Only a subset of metadata fields is shown; the image data is complete, not a thumbnail or a truncated example:

{
  "jsonrpc": "2.0",
  "id": 14,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"issue\":{\"id\":123},\"attachment\":{\"id\":456,\"version_id\":789,\"version\":2},\"analysis_supported\":true}"
      },
      {
        "type": "image",
        "data": "R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7",
        "mimeType": "image/gif"
      }
    ],
    "isError": false
  }
}

In this hypothetical version read, the request uses id: 123, attachment_id: 789, and version: true. The response retains the parent attachment ID 456, while version_id: 789 and version: 2 describe the selected version. File metadata and image bytes come from that selected version; privacy remains that of the parent attachment. With version omitted or false, attachment_id instead means an Attachment.id; neither mode falls back to the other table. Issue, parent attachment, and selected version access are enforced server-side. See Issue attachment tools for arguments and examples.

There is no image-size limit in this tool. Images are returned unchanged, without thumbnails, resizing, conversion, or truncation. max_bytes (default 256 KiB, maximum 1 MiB) applies only to text-like reads and explicit content_format: "text", not to images in auto mode. Unsupported non-image binary files still return metadata only with analysis_supported: false.

Client/provider payload limits and supported image formats are external to this contract and are not bypassed by the code. Handling the complete original image requires memory proportional to its size plus its base64 representation. An image block does not guarantee that every client/provider can accept or analyze that image.

Error codes

  • invalid JSON: -32700, HTTP 400
  • malformed JSON-RPC request: -32600, HTTP 400
  • unsupported method: -32601, HTTP 200
  • invalid tool params: -32602, HTTP 200

notifications/initialized

Supported as a client notification after initialization.

This notification does not require an id.

Example workflow

Typical flow for an MCP client:

  1. Call initialize.
  2. Call tools/list.
  3. Call easy8_projects_list or easy8_issues_list to discover context.
  4. Call easy8_issues_get for detail.
  5. Call easy8_issues_create or easy8_issues_update if the user has permission.

Additional examples:

  • resolve a project with easy8_projects_list, create an issue with easy8_issues_create, then add a comment with easy8_issues_comments_create
  • create a version with easy8_project_versions_create before assigning issues to a release
  • log work with easy8_time_entries_create using either issue_id or project_id
  • triage support work with easy8_helpdesk_sla_events_list and then inspect the linked issue with easy8_issues_get
  • review attendance with easy8_attendances_list and discover activity types with easy8_attendance_activities_list
  • review CRM case follow-ups with easy8_crm_cases_list filtered by assigned_to_id: "me" and active: true; this is for CRM cases only, not issues/tasks or customer-account segmentation
  • segment issues/tasks by linked customer account attributes with easy8_issues_list account filters such as account_status_id, account_industry_id, and account_country_code
  • review project finances with easy8_money_project_summaries_get and drill into allowed money item lists
  • use tools/list after plugin installation to discover newly available plugin tools