Docs chevron_right MCP
hub

MCP Server

ProjectCore includes a built-in Model Context Protocol (MCP) server that lets AI agents read and manage your issue tickets. Every call is scoped and authorized as the connected user, identically to what they can do in the web app.

Overview

The MCP endpoint is available at POST /mcp and speaks the MCP Streamable HTTP transport. It is a machine-to-machine endpoint authenticated by a personal MCP bearer token, never by the Devise session cookie.

Authentication

Each user generates their own personal MCP access token from User Settings → Tokens. The token is a bearer token sent in the Authorization header:

Authorization: Bearer <your-mcp-token>

Requests with a missing or invalid token receive a 401 Unauthorized response.

Transport

The server uses the stateless Streamable HTTP transport. Each request is handled independently, so there is no session state to maintain between calls.

Available Tools

list_projects

List the projects the authenticated user can access. Use the returned key as project_key for other tools.

Parameters
  • • (none)
list_board_columns

List the board columns (statuses) for a project. Use the returned name as the status argument for move_issue.

Parameters
  • • project_key (required)
  • • — e.g. "PCORE"
list_issues

List or search issue tickets in a project. Returns each issue's key, title, type, status, assignee, priority, and story points.

Parameters
  • • project_key (required)
  • • query (optional) — search in title
  • • status (optional) — board column name
  • • assignee_email (optional)
  • • sprint_id (optional)
  • • limit (optional, default 50, max 100)
get_issue

Get full details for a single issue by its key, including its description (with embedded images rendered as markdown links to fetchable URLs) and subtasks.

Parameters
  • • key (required) — e.g. "PCORE-43"
create_issue

Create a new issue ticket in a project. Use list_projects / list_board_columns first to discover valid keys and statuses.

Parameters
  • • project_key (required)
  • • title (required)
  • • description (optional)
  • • issue_type (optional) — task | bug | story | epic
  • • priority (optional) — low | medium | high | urgent
  • • story_points (optional)
  • • assignee_email (optional)
  • • parent_key (optional)
  • • epic_key (optional)
  • • sprint_id (optional)
  • • status (optional)
  • • due_date (optional) — ISO8601
  • • start_date (optional) — ISO8601
create_comment

Add a comment to an issue ticket, identically to posting a comment in the web UI. Anyone who can view the issue's project can comment.

Parameters
  • • key (required) — e.g. "PCORE-43"
  • • body (required) — plain text or simple HTML
update_issue

Update fields on an existing issue. Only pass the fields you want to change.

Parameters
  • • key (required) — e.g. "PCORE-43"
  • • title (optional)
  • • description (optional)
  • • priority (optional)
  • • story_points (optional)
  • • assignee_email (optional) — "unassigned" to clear
  • • sprint_id (optional) — 0 to move to backlog
  • • due_date (optional)
  • • start_date (optional)
move_issue

Move an issue to a different board column/status, like dragging it on the Kanban board. Use list_board_columns to see valid status names.

Parameters
  • • key (required)
  • • status (required) — target column name
  • • position (optional) — 0-based index within column
delete_issue

Permanently delete an issue ticket and its subtasks. This cannot be undone.

Parameters
  • • key (required)

Example Request

List issues in the "In Progress" column of project PCORE:

curl -X POST https://your-workspace.example.com/mcp \
  -H "Authorization: Bearer $MCP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "list_issues",
      "arguments": {
        "project_key": "PCORE",
        "status": "In Progress"
      }
    },
    "id": 1
  }'

Authorization

shield

Every tool call is authorized through the same policies used by the web UI. An AI agent connected as a given user can only see and modify exactly what that user could in the browser. No role check is bypassed.