Skip to content

feat(kiloclaw): add Linear MCP* integration#1407

Merged
evanjacobson merged 31 commits intomainfrom
feature/kiloclaw-linear-cli
Mar 27, 2026
Merged

feat(kiloclaw): add Linear MCP* integration#1407
evanjacobson merged 31 commits intomainfrom
feature/kiloclaw-linear-cli

Conversation

@evanjacobson
Copy link
Copy Markdown
Contributor

@evanjacobson evanjacobson commented Mar 23, 2026

Summary

Adds Linear as an integrated developer tool in KiloClaw, backed by the official Linear MCP server via mcporter.

  • Secret catalog: Adds LINEAR_API_KEY field with lin_api_ validation pattern, icon, and help link to Linear security settings
  • Bootstrap: New configureLinear step that wires up the env var; updateToolsMdLinearSection appends/removes a bounded reference section in TOOLS.md pointing agents to the Linear MCP server and mcporter skill
  • MCP integration: When LINEAR_API_KEY is set, writeMcporterConfig() adds the Linear MCP server entry (key stored as ${LINEAR_API_KEY} verbatim, read from env by mcporter); entry is removed when the key is unset. Preserves existing user-configured servers. No credentials are ever written to disk.
  • Dashboard UI: Adds Linear to the "Developer Tools" section in SettingsTab, new LinearIcon SVG component, and secret-ui-adapter wiring (icon map + description)
  • Tests: Full coverage for configureLinear, updateToolsMdLinearSection, writeMcporterConfig (add, remove, preserve, multi-server), and updated catalog/route assertions

Verification

  • pnpm format:check passes
  • pnpm lint passes
  • Tests pass (vitest in kiloclaw workspace)
  • E2E tested on a fresh instance

Visual Changes

image image

Reviewer Notes

  • Originally prototyped with @schpet/linear-cli installed in the Docker image, but switched to the official Linear MCP server — it's a better fit since mcporter is already deployed on all instances and avoids writing API keys to disk
  • The TOOLS.md section uses <!-- BEGIN:linear --> / <!-- END:linear --> markers, same pattern as the other tool sections
  • No Dockerfile changes — the MCP approach requires no additional system packages

validationPattern: '^lin_api_[a-zA-Z0-9_-]{40}$',
validationMessage:
'Linear API keys start with lin_api_ followed by 40 alphanumeric, underscore, or hyphen characters.',
maxLength: 100,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be shortened to 50 safely (or 48 exactly), however the other entries in this catalog also pad their keys substantially, and it arguably provides a better UX when matched with the regex (for example, if whitespace was copied in addition to the key)

RUN npm install -g @schpet/linear-cli@1.11.1

# Clean up xz-utils now that Node.js and linear-cli are installed
RUN apt-get purge -y xz-utils \
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

linear-cli requires node for install

@evanjacobson evanjacobson changed the title Feature/kiloclaw linear cli feat(kiloclaw): add Linear CLI integration Mar 26, 2026
RUN npm install -g @kilocode/cli@7.0.46

# Install Linear CLI (issue tracker)
RUN npm install -g @schpet/linear-cli@1.11.1
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are security vulnerabilities on a dependency of this package. I have posted a PR to fix them.

I will bump the version to the latest release after it merges.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are security vulnerabilities on a dependency of this package. I have posted a PR to fix them.

I will bump the version to the latest release after it merges.

I am still discussing the changes with the repo owner. This may need to be a follow-up. The vulnerabilities are not exposed in linear-cli regardless.

@evanjacobson evanjacobson marked this pull request as ready for review March 26, 2026 06:46
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Mar 26, 2026

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
kiloclaw/controller/src/config-writer.ts 355 Linear mcporter config writes ${LINEAR_API_KEY} literally, so the MCP server gets an invalid bearer token
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
cloud-agent-next/src/session-service.ts 588 isInteractive now only stays true when createdOnPlatform is empty, but the web routers still pass cloud-agent-web, so web sessions now get question: 'deny' and lose interactive prompts
Files Reviewed (14 files)
  • kiloclaw/Dockerfile - 0 new issues
  • kiloclaw/Dockerfile.local - 0 new issues
  • kiloclaw/controller/src/bootstrap.test.ts - 0 new issues
  • kiloclaw/controller/src/bootstrap.ts - 0 new issues
  • kiloclaw/controller/src/config-writer.test.ts - 0 new issues
  • kiloclaw/controller/src/config-writer.ts - 1 issue
  • kiloclaw/packages/secret-catalog/src/__tests__/catalog.test.ts - 0 new issues
  • kiloclaw/packages/secret-catalog/src/catalog.ts - 0 new issues
  • kiloclaw/packages/secret-catalog/src/types.ts - 0 new issues
  • kiloclaw/src/routes/kiloclaw.test.ts - 0 new issues
  • src/app/(app)/claw/components/SettingsTab.tsx - 0 new issues
  • src/app/(app)/claw/components/icons/LinearIcon.tsx - 0 new issues
  • src/app/(app)/claw/components/secret-ui-adapter.ts - 0 new issues
  • cloud-agent-next/src/session-service.ts - 1 issue

Reviewed by gpt-5.4-20260305 · 2,668,867 tokens

The /root volume persists across redeploys, so `linear auth login --plaintext`
leaves credentials on disk that survive after LINEAR_API_KEY is removed from
env. Now configureLinear() removes ~/.config/linear/ (credentials.toml +
linear.toml) when no API key is set, matching the cleanup pattern used by
configureGitHub().
These files store API secrets, so credential cleanup failures should
not be silently swallowed. Split the two rm calls into independent
try/catch blocks so both are always attempted, and surface the error
message in warnings since rm -rf/-f already exit 0 for absent targets.
Cover the second rm failure, both rm calls failing simultaneously,
and non-Error thrown values exercising the instanceof fallback.
// Remove any previously stored credentials from the persistent volume.
// The CLI recreates ~/.config/linear/ via ensureDir on next auth login.
try {
deps.execFileSync('rm', ['-rf', '/root/.config/linear'], { stdio: 'pipe' });
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// The CLI recreates ~/.config/linear/ via ensureDir on next auth login.
try {
deps.execFileSync('rm', ['-rf', '/root/.config/linear'], { stdio: 'pipe' });
deps.execFileSync('rm', ['-f', '/root/.linear.toml'], { stdio: 'pipe' });
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// The CLI recreates ~/.config/linear/ via ensureDir on next auth login.
// rm -rf/-f exit 0 when the target is absent, so errors here are
// genuine failures (permissions, I/O) worth surfacing.
try {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

separately trying each file delete operation out of an abundance of caution — if one fails, the other one is still tried.

deps.execFileSync('rm', ['-rf', '/root/.config/linear'], { stdio: 'pipe' });
} catch (err) {
console.warn(
`WARNING: failed to remove /root/.config/linear: ${err instanceof Error ? err.message : err}`
Copy link
Copy Markdown
Contributor Author

@evanjacobson evanjacobson Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other warnings logged after a catch in this file do not contain the error, but these are intentionally included, as these files contain credentials and need to be deleted

Cc: line 364

@evanjacobson evanjacobson self-assigned this Mar 26, 2026
- Simplify configureLinear(): remove CLI credential cleanup (rm -rf of
  ~/.config/linear and ~/.linear.toml) since the MCP integration leaves
  no on-disk artifacts
- Remove deps parameter from configureLinear() — no longer executes
  shell commands
- Update TOOLS.md Linear section JSDoc to reference MCP instead of CLI
- Simplify configureLinear tests from 8 CLI-focused tests to 3 MCP tests
- Fix updateToolsMdLinearSection test assertion to match actual mcporter
  content
- Add Linear MCP server entry to writeMcporterConfig(), following the
  same add/remove pattern as AgentCard
- Use literal ${LINEAR_API_KEY} in Authorization header (resolved at
  runtime by 1Password, not interpolated by JS)
- Add comprehensive tests for Linear MCP config lifecycle
@evanjacobson evanjacobson force-pushed the feature/kiloclaw-linear-cli branch from e811161 to b466318 Compare March 27, 2026 02:32
## Summary

A refactor targeting #1407:

After exploring other options for the Linear integration, the official
Linear MCP server turned out to be a better fit than the CLI. All
OpenClaw instances are already deployed with the `mcporter` package and
skill, which give KiloClaw MCP abilities anyways. Importantly, unlike
the CLI, mcporter also allows us to avoid ever writing our actual API
key to a file, which significantly reduces the overhead for managing
this integration. This PR targets feature/kiloclaw-linear-cli with the
scoped changes to switch-over to this MCP integration only, to simplify
the reviewer's experience.

## Changes

- Undo the changes to both `Dockerfile`s — the target branch will have
no diff after this PR merges.
- Strip all on-disk credential cleanup logic from `configureLinear()` —
no new files to manage anymore, so the function no longer needs
`BootstrapDeps`
- Add Linear MCP server entry to `writeMcporterConfig()` when
`LINEAR_API_KEY` is set; remove it when unset. Preserves existing
user-configured servers. The key is stored in the file as
`${LINEAR_API_KEY}` verbatim and read from the environment by mcporter.
- Replace CLI usage documentation in the TOOLS.md agent section with a
pointer to the Linear MCP server and mcporter skill
- Simplify `configureLinear` tests (no more fs/exec mocking) and add
`writeMcporterConfig` tests covering add, remove, preserve, and
multi-server scenarios

## Verification

- [x] `pnpm format:check` passes
- [x] `pnpm lint` passes
- [x] Tests pass (`vitest` in kiloclaw workspace)
- [x] E2E tested on a fresh instance

## New Loom — Kilo Team only
https://www.loom.com/share/5ca9897104e84a3baf560818b7a3bcf7

## Action for reviewer
Please let me know your preference for merge, whether it's into the
feature/kiloclaw-cli branch, or into main directly.
@evanjacobson evanjacobson changed the title feat(kiloclaw): add Linear CLI integration feat(kiloclaw): add Linear MCP* integration Mar 27, 2026
if (env.LINEAR_API_KEY) {
existingServers['linear'] = {
url: 'https://mcp.linear.app/mcp',
headers: { Authorization: 'Bearer ${LINEAR_API_KEY}' },
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is intentionally not interpolated. mcporter supports this behavior.

@evanjacobson evanjacobson merged commit 5e53cad into main Mar 27, 2026
13 checks passed
@evanjacobson evanjacobson deleted the feature/kiloclaw-linear-cli branch March 27, 2026 17:38
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.

2 participants