Skip to main content

MCP Integration

Align exposes a Model Context Protocol (MCP, spec 2025-03-26) endpoint that lets AI assistants — including Claude for Desktop, Cursor, and any MCP-compatible client — read project data and take actions directly inside Align.

Enterprise add-on

MCP access is toggled per workspace by a platform admin. Contact your Align administrator to enable it for your organization.

Connecting your MCP client

Endpoint URL

https://<your-align-host>/mcp

Authentication

Align supports two authentication methods for MCP clients. Both produce an identical experience for your AI tools — choose the one that fits your deployment.

Option A — API key (simpler, server-to-server)

Create or copy an organization-scoped API key from Settings → Developer → API Keys, then pass it as a Bearer token:

Authorization: Bearer <your-api-key>

API keys are good for server-side integrations and scripts where there is no end-user involved.

Align implements a full OAuth 2.0 Authorization Server (PKCE, dynamic client registration, RFC 8414 discovery). This lets an MCP client obtain a short-lived access token on behalf of a specific Align user without ever seeing that user's password or API key.

Discovery endpoint (RFC 8414):

GET https://<your-align-host>/.well-known/oauth-authorization-server

Returns the full server metadata including all endpoint URLs, supported scopes, and PKCE requirements.

OAuth flow (Authorization Code + PKCE):

sequenceDiagram
participant C as MCP Client
participant A as Align OAuth AS
participant U as User (browser)

C->>A: POST /oauth/clients (register)
A-->>C: client_id + client_secret

C->>U: Redirect → GET /oauth/authorize?code_challenge=...
U->>A: Browser GETs consent screen
A-->>U: Align consent page (scopes listed)
U->>A: POST /oauth/authorize (decision=approve)
A-->>U: Redirect → redirect_uri?code=...
U->>C: Auth code delivered via redirect

C->>A: POST /oauth/token (code + code_verifier + client_secret)
A-->>C: access_token (1 h) + refresh_token (30 d)

C->>A: POST /mcp (Bearer access_token)
A-->>C: MCP response

Note over C,A: When access_token expires
C->>A: POST /oauth/token (grant_type=refresh_token)
A-->>C: New access_token + rotated refresh_token
  1. Register your client (once, or on first run):

    POST /oauth/clients
    Content-Type: application/json

    {
    "client_name": "My MCP Client",
    "redirect_uris": ["https://my-client/callback"],
    "scope": "mcp:read mcp:write"
    }

    Response includes client_id and client_secret. Store these securely.

  2. Start the authorization flow — redirect the user to:

    GET /oauth/authorize
    ?client_id=<client_id>
    &redirect_uri=<redirect_uri>
    &response_type=code
    &scope=mcp:read mcp:write
    &state=<random-state>
    &code_challenge=<S256-challenge>
    &code_challenge_method=S256

    The user sees an Align-hosted consent screen and approves the requested scopes.

  3. Exchange the code for tokens:

    POST /oauth/token
    Content-Type: application/x-www-form-urlencoded

    grant_type=authorization_code
    &code=<authorization-code>
    &redirect_uri=<redirect_uri>
    &client_id=<client_id>
    &client_secret=<client_secret>
    &code_verifier=<pkce-verifier>

    Response:

    {
    "access_token": "...",
    "token_type": "Bearer",
    "expires_in": 3600,
    "refresh_token": "...",
    "scope": "mcp:read mcp:write"
    }
  4. Refresh when the access token expires:

    POST /oauth/token
    Content-Type: application/x-www-form-urlencoded

    grant_type=refresh_token
    &refresh_token=<refresh_token>
    &client_id=<client_id>
    &client_secret=<client_secret>

    Each refresh rotates both tokens. The old refresh token is immediately revoked.

  5. Revoke a token when done:

    POST /oauth/revoke
    Content-Type: application/x-www-form-urlencoded

    token=<access_or_refresh_token>
    &client_id=<client_id>
    &client_secret=<client_secret>

Supported scopes:

ScopeAccess granted
mcp:readResources (projects, entries, releases) and search
mcp:writeAll read access + mutating tools (entry.create, entry.update_status, etc.)

Security notes:

  • PKCE (S256) is mandatory for all clients. Plain code_challenge_method is rejected.
  • Authorization codes are single-use (marked on first exchange).
  • Refresh tokens are rotated on every use to limit exposure if stolen.
  • All token values are stored as SHA-256 hashes only — plaintexts are never persisted.

Supported transports

TransportEndpointWhen to use
Streamable HTTP (preferred)POST /mcpClaude for Desktop ≥ 0.7, Cursor, most modern clients
HTTP + SSE fallbackGET /mcp/sse + POST /mcp/messagesOlder clients that require the SSE transport

Replit Agent

Add the following to your Replit Agent's tool configuration (.replit or agent settings panel):

{
"mcpServers": {
"align": {
"type": "http",
"url": "https://<your-align-host>/mcp",
"headers": {
"Authorization": "Bearer <your-api-key>"
}
}
}
}

Once configured, the agent can call resources/list, tools/list, and tools/call against your Align workspace. For example, asking the agent to "create a bug report for the login page in project X" will invoke entry.create and return the new entry ID.

Claude for Desktop (claude_desktop_config.json)

Option A — API key (quickest setup)

{
"mcpServers": {
"align": {
"type": "http",
"url": "https://<your-align-host>/mcp",
"headers": {
"Authorization": "Bearer <your-api-key>"
}
}
}
}

Option B — OAuth 2.0 (user-scoped access, recommended)

Claude for Desktop (≥ 0.7) with native HTTP MCP support will auto-discover the OAuth server and prompt the user to authorize. Follow these steps:

  1. Add the server to claude_desktop_config.json without any auth headers:

    {
    "mcpServers": {
    "align": {
    "type": "http",
    "url": "https://<your-align-host>/mcp"
    }
    }
    }
  2. Restart Claude for Desktop. It will detect that the MCP server requires auth by reading the discovery document at /.well-known/oauth-authorization-server.

  3. Claude opens your browser to the Align consent screen at /oauth/authorize. Sign in with your Align account and click Approve.

  4. Claude receives the OAuth token via the PKCE redirect and stores it locally. All subsequent MCP calls use the token automatically.

  5. Token refresh happens transparently — Claude handles the refresh grant before the 1-hour access token expires, using the 30-day refresh token.

  6. Revoke access at any time: in Align go to Settings → Developer → Authorized Apps (coming in task #416), or call POST /oauth/revoke directly:

    POST /oauth/revoke
    Content-Type: application/x-www-form-urlencoded

    token=<access_or_refresh_token>
    &client_id=<client_id>
    &client_secret=<client_secret>
note

Claude for Desktop performs dynamic client registration on first connect — it calls POST /oauth/clients automatically. You do not need to pre-register a client manually when using Claude for Desktop.


Real-time resource subscriptions (SSE transport)

When connected via the HTTP + SSE fallback transport (GET /mcp/sse), clients can subscribe to live resource change notifications. The server pushes notifications/resources/updated messages whenever the underlying data changes.

Subscribe:

{ "jsonrpc": "2.0", "id": 1, "method": "resources/subscribe", "params": { "uri": "align://projects/{id}/entries" } }

Unsubscribe:

{ "jsonrpc": "2.0", "id": 2, "method": "resources/unsubscribe", "params": { "uri": "align://projects/{id}/entries" } }

Notification delivered by the server:

{ "jsonrpc": "2.0", "method": "notifications/resources/updated", "params": { "uri": "align://projects/{id}/entries" } }

Subscribable URIs and triggering events:

URI patternNotified when…
align://projectsAny entry or release is created/updated across the workspace
align://projects/{id}An entry or release in that project is created/updated
align://projects/{id}/entriesAn entry in that project is created, updated, or commented on
align://entries/{id}That specific entry is updated, status-changed, reassigned, or commented on
align://releasesAny release is created, status-changed, or released

Subscriptions are scoped to the current SSE session and are automatically cleaned up when the connection closes. The Streamable HTTP transport (POST /mcp) does not support push subscriptions; reconnect using the SSE transport if you need live notifications.


Resources

Resources are read-only data sources the AI can retrieve.

URIDescription
align://projectsAll projects in your workspace
align://projects/{id}Single project detail
align://projects/{id}/entriesAll entries for a project
align://entries/{id}Entry detail including comments
align://releasesAll releases across your workspace
align://task-mappingsCross-system entry ↔ external-task mappings

Tools

Tools allow the AI to take actions in Align. All tool calls are audit-logged.

entry.create

Create a new entry in a project.

ParameterTypeRequiredDescription
projectIdstringTarget project ID
titlestringEntry title (max 500 chars)
typeenumfeature_request, bug_report, feedback, validation, documentation, platform_infrastructure, ci_cd, security
descriptionstringMarkdown description
priorityenumlow, medium (default), high, critical
statusenumopen (default), assigned, in_progress, deployed, solved
assignedToIdstringUser ID to assign the entry to

entry.update_status

Update the status, priority, or assignee of an existing entry.

ParameterTypeRequiredDescription
entryIdstringEntry ID
statusenumNew status
priorityenumNew priority
assignedToIdstring | nullNew assignee, or null to unassign

entry.add_comment

Add a comment to an existing entry.

ParameterTypeRequiredDescription
entryIdstringEntry ID
contentstringComment text (markdown supported)

Create or update a mapping between an Align entry and an external task (Replit task, Jira issue, Linear ticket, etc.).

ParameterTypeRequiredDescription
entryIdstringAlign entry ID
systemstringExternal system identifier e.g. replit, jira, linear
externalIdstringID of the task in the external system
externalRefstringHuman-readable reference e.g. #386
externalUrlstringDeep-link URL to the external task

task.sync_from_external

Idempotent upsert: create or update an Align entry from an external task payload and maintain the mapping. Use this to keep Align in sync with an external tracker without creating duplicates.

ParameterTypeRequiredDescription
systemstringExternal system identifier
externalIdstringID in the external system
projectIdstringAlign project ID
titlestringEntry title
descriptionstringEntry description
typeenumEntry type (default feature_request)
statusenumEntry status (default open)
priorityenumEntry priority (default medium)
externalRefstringe.g. #386
externalUrlstringDeep-link URL

search.global

Full-text search across projects and entries in your workspace.

ParameterTypeRequiredDescription
qstringSearch query
limitnumberMax results (1–100, default 50)

Prompts

Prompts are reusable AI prompt templates with live data interpolated.

summarise_project_status

Generates a project health summary prompt with current metrics (open/resolved counts, active release, etc.).

Arguments: projectId (string)

create_issue_from_context

Guides the AI to draft a well-formed Align entry from freeform context text.

Arguments: context (string), projectId (string, optional)


Rate limiting

MCP requests share the same per-key rate limit as the v1 REST API: 600 requests per minute. The response includes standard rate-limit headers:

X-RateLimit-Limit: 600
X-RateLimit-Remaining: 599
X-RateLimit-Reset: <unix-timestamp>

When the limit is exceeded the server returns 429 Too Many Requests with a Retry-After header.


Audit log

Every tool invocation is written to an internal audit log. Only a SHA-256 hash of the tool arguments is stored — raw arguments are never persisted. Platform admins can query the log via the database.


Troubleshooting

ErrorMeaning
401 UnauthorizedCredentials missing, revoked, or expired (API key or OAuth token)
403 ForbiddenMCP not enabled for this workspace — contact your platform admin
403 Forbidden (project key)Project-scoped API keys are not supported for MCP v1. Generate an organization-scoped key from Settings → Developer → API Keys
400 Bad Request (invalid_grant)OAuth authorization code is invalid, already used, or expired
400 Bad Request (invalid_client)OAuth client_id / client_secret mismatch, or unknown client
400 Bad Request (invalid_request)PKCE code_verifier does not match the stored code_challenge, or required parameter is missing
400 Bad Request (unsupported_grant_type)Only authorization_code and refresh_token are supported
423 LockedWorkspace suspended due to billing — update payment method at /settings/billing
429 Too Many RequestsRate limit exceeded; wait for Retry-After seconds
404 Not Found (SSE session)SSE session expired; reconnect via GET /mcp/sse

API key scope requirement

MCP v1 requires an organization-scoped API key. Project-scoped keys (created from a specific project's settings) are intentionally rejected because they carry least-privilege access to a single project, and elevating them to org-wide MCP access (all projects, releases, search, and write tools) would violate the principle of least privilege. Support for project-scoped MCP access is planned for a future phase.