Skip to content

Adding linear support via mcp#586

Open
tylermmorton wants to merge 1 commit into
mattpocock:mainfrom
tylermmorton:linear-backlog-manager
Open

Adding linear support via mcp#586
tylermmorton wants to merge 1 commit into
mattpocock:mainfrom
tylermmorton:linear-backlog-manager

Conversation

@tylermmorton
Copy link
Copy Markdown

@tylermmorton tylermmorton commented May 7, 2026

I've been hacking on adding Linear as a backlog management option via Linear's MCP server based on comments in #518 -- Generated from the following claude plan. Still testing and working out issues, but I'm open to feedback on design and implementation

Linear Backlog Manager Integration (MCP)

Context

Sandcastle supports pluggable backlog managers (GitHub Issues, Beads) selected at sandcastle init time. The goal is to add Linear as a third option using the Linear MCP server (@tacticlaunch/mcp-linear) instead of a curl-based CLI script. The MCP approach is simpler — no team ID or state UUIDs required, just an API token — and gives the agent richer tool access via Claude Code's native MCP support.

The current templates use !{{LIST_TASKS_COMMAND}}\`` to run a shell command inline in prompts. MCP tools aren't invoked this way; the agent calls them directly. This requires a new LIST_TASKS_SNIPPET` template variable that holds the full invocation style (shell command for CLI managers, tool description for MCP managers).


Implementation

1. src/InitService.ts — interface change

Add LIST_TASKS_SNIPPET to BacklogManagerEntry.templateArgs interface (~line 223):

readonly LIST_TASKS_SNIPPET: string;

This replaces the hardcoded !backtick`` usage in prompt templates with a substitutable block.

2. src/InitService.ts — update existing entries

Add LIST_TASKS_SNIPPET to the GitHub Issues entry:

LIST_TASKS_SNIPPET: "!`gh issue list --state open --label Sandcastle --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'`",

Add LIST_TASKS_SNIPPET to the Beads entry:

LIST_TASKS_SNIPPET: "!`bd ready --json`",

3. src/InitService.ts — add LINEAR_TOOLS and registry entry

After BEADS_TOOLS (~line 256), add:

const LINEAR_TOOLS = `# Configure Official Linear MCP server for Claude Code
# Settings will be relocated to /home/agent/.claude/ by the subsequent usermod command
RUN mkdir -p /home/node/.claude \\
  && echo '{"mcpServers":{"linear":{"url":"https://mcp.linear.app/mcp"}}}' > /home/node/.claude/settings.json \\
  && chown -R node:node /home/node/.claude`;

Key details:

  • Writes to /home/node/.claude/settings.json — the subsequent usermod -d /home/agent -m -l agent node in the Dockerfile moves this to /home/agent/.claude/settings.json
  • chown -R node:node ensures the agent user (UID 1000, renamed from node) can read/write the settings
  • Uses the official Linear remote MCP URL — no packages to install
  • Authentication is handled via OAuth at connection time (Linear's MCP uses OAuth 2.1)

Add Linear entry to BACKLOG_MANAGER_REGISTRY:

{
  name: "linear",
  label: "Linear",
  templateArgs: {
    LIST_TASKS_SNIPPET: "Use the `mcp__linear-server__list_issues` tool to list open issues (filter by `state: \"Todo\"`).",
    LIST_TASKS_COMMAND: "mcp__linear-server__list_issues",
    VIEW_TASK_COMMAND: "mcp__linear-server__get_issue",
    CLOSE_TASK_COMMAND: "mcp__linear-server__save_issue (set state: \"Done\")",
    BACKLOG_MANAGER_TOOLS: LINEAR_TOOLS,
  },
  envExample: `# Linear MCP authentication is handled via OAuth when the agent container first connects.
# Visit https://linear.app/docs/mcp for setup instructions.`,
},

Note: LIST_TASKS_COMMAND is kept to satisfy the interface but is no longer used by templates.

4. Update 3 prompt templates

Replace !{{LIST_TASKS_COMMAND}}\`` with {{LIST_TASKS_SNIPPET}}` in:

  • src/templates/simple-loop/prompt.md (line 5)
  • src/templates/sequential-reviewer/implement-prompt.md (line 5)
  • src/templates/parallel-planner/plan-prompt.md (line 7)

5. Delete linear-cli.sh from all template directories

Remove the 5 files added in the previous curl-based implementation:

  • src/templates/blank/linear-cli.sh
  • src/templates/simple-loop/linear-cli.sh
  • src/templates/sequential-reviewer/linear-cli.sh
  • src/templates/parallel-planner/linear-cli.sh
  • src/templates/parallel-planner-with-review/linear-cli.sh

6. Update changeset

Update .changeset/linear-backlog-manager.md body if needed.


Key files

File Change
src/InitService.ts:223 Add LIST_TASKS_SNIPPET to interface
src/InitService.ts:258 Update GitHub Issues + Beads entries
src/InitService.ts:258 Add LINEAR_TOOLS + Linear registry entry
src/templates/simple-loop/prompt.md:5 !{{LIST_TASKS_COMMAND}}\`` → {{LIST_TASKS_SNIPPET}}`
src/templates/sequential-reviewer/implement-prompt.md:5 same
src/templates/parallel-planner/plan-prompt.md:7 same
src/templates/*/linear-cli.sh Delete (5 files)

Verification

  1. npm run typecheck — no type errors
  2. npm test — no new failures (44 pre-existing failures expected)
  3. Manual: sandcastle init shows "Linear" as backlog manager option
  4. Select Linear — generated Dockerfile contains npm install -g @tacticlaunch/mcp-linear and settings.json creation; .env.example contains only LINEAR_API_TOKEN
  5. Generated prompt.md uses {{LIST_TASKS_SNIPPET}} value (MCP tool description) instead of !backtick command```

@vercel
Copy link
Copy Markdown

vercel Bot commented May 7, 2026

@tylermmorton is attempting to deploy a commit to the Matt Pocock's projects Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant