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.
- • (none)
list_board_columns
List the board columns (statuses) for a project. Use the returned name as the status argument for move_issue.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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.
- • 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
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.