集成

Linear

通过托管的 OAuth GraphQL 接口查询与管理 Linear 的 issue、项目、团队、周期、标签和评论。

它能做什么

通过 Maton 托管的 OAuth 端点接入 Linear,使用 GraphQL 读写 issue、项目、团队、周期、标签、工作流状态、用户和评论。文档给出了 CLI、Python 和 JavaScript 三种调用方式,覆盖 Maton API Key 认证、多 Linear 连接管理,以及列表、搜索、创建、更新等常见操作。CLI 自动处理基于游标的分页;类似 ABC-123 的标识符可直接替代 UUID 使用。所有写操作都需要先获得用户明确确认;部分变更操作可能依赖额外的 OAuth 权限,遇到权限错误需联系 Maton 申请扩展。

什么时候用它

  • 按团队列出并筛选 Linear issue
  • 按关键词全文搜索 issue
  • 创建或更新 issue,并添加评论
  • 管理多个 Linear OAuth 连接以对接不同工作区

技能文档

Linear

Access the Linear API with managed OAuth authentication. Query and manage issues, projects, teams, cycles, labels, and comments using GraphQL.

Quick Start

CLI:

maton linear issue list -c ABC -L 10
maton api '/linear/graphql'

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'query': '{ viewer { id name email } }'}).encode()
req = urllib.request.Request('https://api.maton.ai/linear/graphql', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://api.maton.ai/linear/graphql

All requests use POST to the GraphQL endpoint. Maton proxies requests to api.linear.app and automatically injects your OAuth token.

Installation

NPM:

npm install -g @maton/cli

Homebrew:

brew install maton-ai/cli/maton

Authentication

CLI:

maton login                          # Opens browser for API key
maton login --interactive            # Skip browser, paste API key directly
maton whoami                         # Show current auth state

Manual:

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key
  4. Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"

Connection Management

Manage your Linear OAuth connections at https://api.maton.ai.

List Connections

CLI:

maton connection list linear --status ACTIVE
maton api -X GET /connections -f app=linear -f status=ACTIVE

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=linear&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

CLI:

maton connection create linear
maton api /connections -f app=linear

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'linear'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

CLI:

maton connection view {connection_id}
maton api /connections/{connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "connection": {
    "connection_id": "{connection_id}",
    "status": "ACTIVE",
    "creation_time": "2026-02-04T23:03:22.676001Z",
    "last_updated_time": "2026-02-04T23:03:51.239577Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "linear",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

CLI:

maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple Linear connections, specify which one to use:

CLI:

maton linear issue list -c ABC --connection {connection_id}
maton api /linear/graphql --connection {connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'query': '{ viewer { id name } }'}).encode()
req = urllib.request.Request('https://api.maton.ai/linear/graphql', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If you have multiple connections, always specify the connection to ensure requests go to the intended account.

Security & Permissions

  • Access is scoped to issues, projects, teams, cycles, and comments within the connected Linear account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.

API Reference

Linear uses a GraphQL API. All operations are sent as POST requests with a JSON body containing the query field.

Viewer (Current User)

POST /linear/graphql
Content-Type: application/json

{"query": "{ viewer { id name email } }"}

Example:

maton linear whoami

Organization

POST /linear/graphql
Content-Type: application/json

{"query": "{ organization { id name urlKey } }"}

Example:

maton linear org view

Teams

List Teams

POST /linear/graphql
Content-Type: application/json

{"query": "{ teams { nodes { id name key } } }"}

Example:

maton linear team list

Get Team

POST /linear/graphql
Content-Type: application/json

{"query": "{ team(id: \"ABC\") { id name key issues { nodes { id identifier title } } } }"}

Example:

maton linear team view ABC

Issues

List Issues

POST /linear/graphql
Content-Type: application/json

{"query": "{ issues(first: 10, filter: { team: { key: { eq: \"ABC\" } } }) { nodes { id identifier title state { name } priority createdAt } pageInfo { hasNextPage endCursor } } }"}

Example:

maton linear issue list -c ABC -L 10

Get Issue by ID or Identifier

POST /linear/graphql
Content-Type: application/json

{"query": "{ issue(id: \"ABC-123\") { id identifier title description state { name } priority assignee { name } team { key name } createdAt updatedAt } }"}

Example:

maton linear issue view ABC-123

Filter Issues

Filter by state type:

POST /linear/graphql
Content-Type: application/json

{"query": "{ issues(first: 10, filter: { state: { type: { eq: \"started\" } } }) { nodes { id identifier title state { name type } } } }"}

Example:

maton linear issue list --state started -L 10

Filter by title:

POST /linear/graphql
Content-Type: application/json

{"query": "{ issues(first: 10, filter: { title: { containsIgnoreCase: \"bug\" } }) { nodes { id identifier title } } }"}

Example:

maton linear issue list --title bug -L 10

Search Issues

POST /linear/graphql
Content-Type: application/json

{"query": "{ searchIssues(first: 10, term: \"shopify\") { nodes { id identifier title } } }"}

Example:

maton linear issue search shopify -L 10

Create Issue

POST /linear/graphql
Content-Type: application/json

{"query": "mutation { issueCreate(input: { teamId: \"TEAM_ID\", title: \"New issue title\" }) { success issue { id identifier title state { name } } } }"}

Example:

maton linear issue create --team-id TEAM_ID -t 'New issue title'

Update Issue

POST /linear/graphql
Content-Type: application/json

{"query": "mutation { issueUpdate(id: \"ABC-123\", input: { title: \"Updated title\", priority: 2 }) { success issue { id identifier title priority } } }"}

Example:

maton linear issue update ABC-123 -t 'Updated title' --priority 2

Projects

List Projects

POST /linear/graphql
Content-Type: application/json

{"query": "{ projects(first: 10) { nodes { id name state createdAt } } }"}

Example:

maton linear project list

Cycles

List Cycles

POST /linear/graphql
Content-Type: application/json

{"query": "{ cycles(first: 10) { nodes { id name number startsAt endsAt } } }"}

Example:

maton linear cycle list

Labels

List Labels

POST /linear/graphql
Content-Type: application/json

{"query": "{ issueLabels(first: 20) { nodes { id name color } } }"}

Example:

maton linear label list

Workflow States

POST /linear/graphql
Content-Type: application/json

{"query": "{ workflowStates(first: 20) { nodes { id name type team { key } } } }"}

Example:

maton linear state list

Users

POST /linear/graphql
Content-Type: application/json

{"query": "{ users(first: 20) { nodes { id name email active } } }"}

Example:

maton linear user list

Comments

List Comments

POST /linear/graphql
Content-Type: application/json

{"query": "{ issue(id: \"ABC-123\") { comments(first: 10) { nodes { id body createdAt user { name } } } } }"}

Example:

maton linear comment list --issue ABC-123 -L 10

Create Comment

POST /linear/graphql
Content-Type: application/json

{"query": "mutation { commentCreate(input: { issueId: \"ABC-123\", body: \"Looking into this\" }) { success comment { id body } } }"}

Example:

maton linear comment create --issue ABC-123 -b 'Looking into this'

Pagination

Linear uses Relay-style cursor-based pagination. The CLI automatically paginates with '--paginate'.

Example:

maton linear issue list -c ABC --paginate

Code Examples

CLI

# List issues for a team
maton linear issue list -c ABC -L 10

# View a specific issue
maton linear issue view ABC-123

# Create a new issue
maton linear issue create --team-id TEAM_ID -t 'Fix login'

# Add a comment
maton linear comment create --issue ABC-123 -b 'Looking into this'

JavaScript

const response = await fetch('https://api.maton.ai/linear/graphql', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query: `{ issues(first: 10) { nodes { id identifier title state { name } } } }`
  })
});
const data = await response.json();

Python

import os
import requests

response = requests.post(
    'https://api.maton.ai/linear/graphql',
    headers={
        'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
        'Content-Type': 'application/json'
    },
    json={
        'query': '{ issues(first: 10) { nodes { id identifier title state { name } } } }'
    }
)
data = response.json()

Notes

  • Linear uses GraphQL exclusively (no REST API)
  • Issue identifiers like ABC-123 can be used in place of UUIDs for the id parameter
  • Priority values: 0 = No priority, 1 = Urgent, 2 = High, 3 = Medium, 4 = Low
  • Workflow state types: backlog, unstarted, started, completed, canceled
  • The GraphQL schema is introspectable at https://api.linear.app/graphql
  • Use searchIssues(term: "...") for full-text search across issues
  • Some mutations (delete, create labels/projects) may require additional OAuth scopes. If you receive a scope error, contact Maton support at [email protected] with the specific operations/APIs you need and your use-case

Error Handling

StatusMeaning
400Missing Linear connection or GraphQL validation error
401Invalid or missing Maton API key
403Insufficient OAuth scope for the operation
429Rate limited
4xx/5xxPassthrough error from Linear API

GraphQL errors are returned in the errors array:

{
  "errors": [
    {
      "message": "Invalid scope: `write` required",
      "extensions": {
        "type": "forbidden",
        "code": "FORBIDDEN",
        "statusCode": 403
      }
    }
  ]
}

Troubleshooting: API Key Issues

CLI:

  1. Check your auth state:
maton whoami
  1. Verify the API key is valid by listing connections:
maton connection list

Manual:

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with linear. For example:
  • Correct: https://api.maton.ai/linear/graphql
  • Incorrect: https://api.maton.ai/graphql

Resources

常见问题

这个技能会调用 Linear 的 REST 接口吗?
不会。Linear 只提供 GraphQL API,技能通过 https://api.maton.ai/linear/graphql 发送带 JSON 查询体的 POST 请求,再由 Maton 转发到 api.linear.app。
认证流程是怎样的?
需要将 Maton API Key 设置为 MATON_API_KEY 环境变量。Linear 的 OAuth 令牌由 Maton 自动托管;当存在多个连接时,可通过 Maton-Connection 请求头或 CLI 的 --connection 参数指定目标连接。
能否创建或修改 issue?
可以。文档涵盖了 issueCreate、issueUpdate 以及 commentCreate 等变更操作。所有写操作在执行前都需要用户明确确认;部分变更可能依赖未默认授予的额外 OAuth 权限。

相关技能

通过自带的 Node CLI 读取与修改 Linear 的 issue、项目和评论。

140 次安装6 星标

通过托管 OAuth 代理对接 Asana API,统一处理任务、项目、空间、用户与 Webhook。

601 次安装6 星标

通过托管 OAuth 调用 LinkedIn REST API,覆盖发文、个人资料、广告账户与广告库。

410 次安装45 星标

通过托管 OAuth 连接 Google Tasks,统一 API 完成任务列表与任务的读写管理。

252 次安装10 星标

通过托管 OAuth 接入 GitHub REST API,覆盖仓库、Issue、PR、Commit、分支与用户等接口。

595 次安装47 星标

通过托管 OAuth 代理访问 Trello API,统一管理看板、列表、卡片、检查项、标签与成员。

587 次安装7 星标

byungkyu 的更多技能

浏览全部技能

通过 Microsoft Graph 接入 Outlook,读取、发送、管理邮件、文件夹、日历事件和联系人,OAuth 由平台托管。

作者 byungkyu771 次安装46 星标

通过托管 OAuth 调用 Jira Cloud API,搜索并管理工单。

作者 byungkyu241 次安装7 星标

Google Slides API integration with managed OAuth. Create presentations, add slides, insert content, and manage slide formatting. Use this skill when users wa...

作者 byungkyu653 次安装33 星标

Google Meet API integration with managed OAuth. Create meeting spaces, list conference records, and manage meeting participants. Use this skill when users wa...

作者 byungkyu619 次安装15 星标

Google Contacts API integration with managed OAuth. Manage contacts, contact groups, and search your address book. Use this skill when users want to create,...

作者 byungkyu233 次安装5 星标

Pipedrive API integration with managed OAuth. Manage deals, persons, organizations, activities, and pipelines. Use this skill when users want to interact wit...

作者 byungkyu621 次安装7 星标