···11+name: Publish MCP Package
22+33+on:
44+ release:
55+ types: [published]
66+77+permissions:
88+ contents: read
99+ id-token: write
1010+1111+jobs:
1212+ publish:
1313+ runs-on: ubuntu-24.04
1414+ if: ${{ startsWith(github.event.release.tag_name, 'mcp-v') }}
1515+1616+ steps:
1717+ - name: Checkout repository
1818+ uses: actions/checkout@v4
1919+2020+ - name: Setup pnpm
2121+ uses: pnpm/action-setup@v4
2222+ with:
2323+ version: 10.32.1
2424+2525+ - name: Setup Node.js
2626+ uses: actions/setup-node@v6
2727+ with:
2828+ node-version: 20.19.0
2929+ cache: pnpm
3030+ registry-url: https://registry.npmjs.org
3131+3232+ - name: Install dependencies
3333+ run: pnpm install --frozen-lockfile
3434+3535+ - name: Run MCP checks
3636+ run: |
3737+ pnpm --filter @kaneo/mcp test
3838+ pnpm --filter @kaneo/mcp build
3939+4040+ - name: Validate MCP release tag
4141+ run: |
4242+ PACKAGE_VERSION=$(node -p "require('./packages/mcp/package.json').version")
4343+ TAG_VERSION="${GITHUB_REF_NAME#mcp-v}"
4444+4545+ if [ "${GITHUB_REF_NAME}" = "${TAG_VERSION}" ]; then
4646+ echo "Release tag must start with mcp-v, got ${GITHUB_REF_NAME}"
4747+ exit 1
4848+ fi
4949+5050+ if [ "${TAG_VERSION}" != "${PACKAGE_VERSION}" ]; then
5151+ echo "Release tag version (${TAG_VERSION}) does not match packages/mcp version (${PACKAGE_VERSION})"
5252+ exit 1
5353+ fi
5454+5555+ - name: Check whether @kaneo/mcp version is already published
5656+ id: version_check
5757+ run: |
5858+ PACKAGE_VERSION=$(node -p "require('./packages/mcp/package.json').version")
5959+6060+ if npm view "@kaneo/mcp@${PACKAGE_VERSION}" version >/dev/null 2>&1; then
6161+ echo "already_published=true" >> "$GITHUB_OUTPUT"
6262+ echo "@kaneo/mcp@${PACKAGE_VERSION} is already published; skipping publish."
6363+ else
6464+ echo "already_published=false" >> "$GITHUB_OUTPUT"
6565+ fi
6666+6767+ - name: Publish @kaneo/mcp
6868+ if: ${{ steps.version_check.outputs.already_published == 'false' }}
6969+ run: |
7070+ cd packages/mcp
7171+ npm publish --access public --provenance
7272+ env:
7373+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+2-2
ENVIRONMENT_SETUP.md
···2626- `KANEO_CLIENT_URL` - The URL of the web application (e.g., `http://localhost:5173`)
2727- `KANEO_API_URL` - The URL of the API (e.g., `http://localhost:1337`)
2828- `AUTH_SECRET` - Secret key for JWT token generation (**must be at least 32 characters long**; use a long, random value in production)
2929-- `DEVICE_AUTH_CLIENT_IDS` - Optional comma-separated list of allowed device-flow client IDs (for example `kaneo-cli,my-app`)
2929+- `DEVICE_AUTH_CLIENT_IDS` - **Optional.** Comma-separated list of allowed device-flow OAuth client IDs. When unset, Kaneo implicitly allows `kaneo-cli` and `kaneo-mcp` by default (no extra configuration for the CLI or MCP). Override only when you need additional trusted clients, for example `kaneo-cli,kaneo-mcp,my-desktop-app`.
3030- `DATABASE_URL` - PostgreSQL connection string
3131- `POSTGRES_DB` - PostgreSQL database name
3232- `POSTGRES_USER` - PostgreSQL username
3333- `POSTGRES_PASSWORD` - PostgreSQL password
34343535-If you are testing a CLI or external app against your local Kaneo instance, set `DEVICE_AUTH_CLIENT_IDS` to include the client ID your app sends to `/api/auth/device/code`.
3535+If your app uses a device client ID that is not included in the defaults, set `DEVICE_AUTH_CLIENT_IDS` to the full comma-separated list of allowed IDs (including any defaults you still need), so it includes the client ID your app sends to `/api/auth/device/code`.
36363737### Development-Specific Variables
3838
+1-1
apps/api/src/auth.ts
···113113 .filter(Boolean),
114114 );
115115 }
116116- return new Set(["kaneo-cli"]);
116116+ return new Set(["kaneo-cli", "kaneo-mcp"]);
117117}
118118119119function getDeviceAuthVerificationUri(): string {
+3-1
apps/docs/api-reference/authentication.mdx
···97979898## Using Device Authorization
9999100100-Before using device authorization on a self-hosted Kaneo instance, the instance operator must allow your client ID through `DEVICE_AUTH_CLIENT_IDS`.
100100+By default, self-hosted Kaneo allows the built-in device clients `kaneo-cli` and `kaneo-mcp`.
101101+102102+If you want to use a different device client ID, the instance operator must allow it through `DEVICE_AUTH_CLIENT_IDS`.
101103102104### Flow overview
103105
···5151Name | Description |
5252--- | --- |
5353| `AUTH_SECRET` | The secret key for the JWT token. **Must be at least 32 characters long**, use a long, random value in production. Example: use `openssl rand -base64 32` to generate a secure key in Linux/macOS.
5454-| `DEVICE_AUTH_CLIENT_IDS` | Comma-separated list of allowed device authorization client IDs. When unset, `kaneo-cli` is allowed by default, so no extra configuration is required for the CLI. Use this to permit trusted external app identifiers such as `kaneo-cli,my-desktop-app`. |
5454+| `DEVICE_AUTH_CLIENT_IDS` | **Optional.** Comma-separated list of allowed device authorization client IDs. When unset, Kaneo implicitly allows `kaneo-cli` and `kaneo-mcp` by default, so no extra configuration is required for the CLI or MCP. Override only when you need additional trusted clients, for example `kaneo-cli,kaneo-mcp,my-desktop-app`. |
555556565757## Optional variables
···153153- If you enable Discord SSO, you need to set up the Discord application which is used to authenticate users in the [Discord Developer Portal](https://discord.com/developers/applications). See the [Discord SSO guide](/core/social-providers/discord).
154154- If you enable Custom OAuth/OIDC, you need to configure your identity provider with the appropriate redirect URI. See the [Custom OAuth/OIDC guide](/core/social-providers/custom-oauth).
155155- If you have enabled SMTP, your sign in will be done via email using a magic link.
156156-- If you want to allow CLI or external-app sign-in through device authorization, set `DEVICE_AUTH_CLIENT_IDS` to the trusted client IDs for your deployment.
156156+- If you need device authorization for clients beyond the defaults (`kaneo-cli`, `kaneo-mcp` when `DEVICE_AUTH_CLIENT_IDS` is unset), set `DEVICE_AUTH_CLIENT_IDS` to the full comma-separated list of trusted client IDs for your deployment.
+96
apps/docs/core/integrations/mcp.mdx
···11+---
22+title: MCP
33+description: Connect Kaneo to MCP clients like Cursor and Claude Desktop using the official Kaneo MCP server.
44+---
55+66+Kaneo ships an official MCP server package, `@kaneo/mcp`, so you can manage workspaces, projects, tasks, comments, and labels from MCP-compatible tools.
77+88+The server runs locally over stdio and authenticates with Kaneo using device authorization.
99+1010+## Prerequisites
1111+1212+- Node.js 20 or newer
1313+- A running Kaneo API
1414+- Access to the Kaneo web app to approve device login
1515+1616+By default, self-hosted Kaneo allows both `kaneo-cli` and `kaneo-mcp` as device auth client IDs.
1717+1818+## Install and register
1919+2020+Use the recommended interactive installer:
2121+2222+```bash
2323+npx @kaneo/mcp
2424+```
2525+2626+The installer lets you choose where to register the server configuration:
2727+2828+- Cursor (user-wide)
2929+- Cursor (project-level)
3030+- Claude Desktop
3131+- Custom JSON config path
3232+3333+You can also run the explicit install command:
3434+3535+```bash
3636+kaneo-mcp install --target cursor-user -y
3737+```
3838+3939+Use `--help` to see all available targets and flags:
4040+4141+```bash
4242+kaneo-mcp install --help
4343+```
4444+4545+## Point to a self-hosted instance
4646+4747+When generating config, pass your Kaneo base URL:
4848+4949+```bash
5050+kaneo-mcp install --target cursor-user -y --api-url https://kaneo.example.com
5151+```
5252+5353+Or set it via environment variable:
5454+5555+| Variable | Description |
5656+| --- | --- |
5757+| `KANEO_API_URL` | Kaneo API origin. Default: `http://localhost:1337`. Do not include `/api`. |
5858+| `KANEO_MCP_CLIENT_ID` | Device auth client ID. Default: `kaneo-mcp`. |
5959+6060+If you override `KANEO_MCP_CLIENT_ID`, make sure it is included in [`DEVICE_AUTH_CLIENT_IDS`](/core/installation/environment-variables).
6161+6262+## Authentication flow
6363+6464+On the first tool call that needs Kaneo access, the MCP server:
6565+6666+1. Requests a device code from Kaneo
6767+2. Prints a verification URL and user code
6868+3. Opens the browser when possible
6969+4. Polls until you approve sign-in
7070+5. Stores credentials in `~/.config/kaneo-mcp/credentials.json`
7171+7272+## Available tools
7373+7474+Current MCP tools include:
7575+7676+- Session: `whoami`, `list_workspaces`
7777+- Projects: `list_projects`, `get_project`, `create_project`, `update_project`
7878+- Tasks: `list_tasks`, `get_task`, `create_task`, `update_task`, `move_task`, `update_task_status`
7979+- Comments: `list_task_comments`, `create_task_comment`
8080+- Labels: `list_workspace_labels`, `create_label`, `attach_label_to_task`, `detach_label_from_task`
8181+8282+## Run manually for debugging
8383+8484+To run the stdio server directly:
8585+8686+```bash
8787+npx @kaneo/mcp serve
8888+```
8989+9090+When running from source in this monorepo:
9191+9292+```bash
9393+pnpm --filter @kaneo/mcp run build
9494+pnpm --filter @kaneo/mcp run start
9595+```
9696+
···11+MIT License
22+33+Copyright (c) 2026 Kaneo MCP contributors
44+55+Permission is hereby granted, free of charge, to any person obtaining a copy
66+of this software and associated documentation files (the "Software"), to deal
77+in the Software without restriction, including without limitation the rights
88+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99+copies of the Software, and to permit persons to whom the Software is
1010+furnished to do so, subject to the following conditions:
1111+1212+The above copyright notice and this permission notice shall be included in all
1313+copies or substantial portions of the Software.
1414+1515+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1616+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1717+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121+SOFTWARE.
+115
packages/mcp/README.md
···11+# Kaneo MCP server
22+33+`@kaneo/mcp` is a local MCP server for Kaneo.
44+55+It runs over stdio, signs in with Kaneo's device flow, and then calls the Kaneo API with a bearer token. The package lives in `packages/mcp` in this monorepo and exposes the `kaneo-mcp` CLI.
66+77+## Prerequisites
88+99+- Node.js 20+
1010+- A running Kaneo API (for example `http://localhost:1337`) and web app (for device approval UI).
1111+1212+Kaneo allows `kaneo-cli` and `kaneo-mcp` by default, so you usually do not need extra server configuration.
1313+1414+If you want to run this server with a different client ID, allow it on the Kaneo server:
1515+1616+```bash
1717+DEVICE_AUTH_CLIENT_IDS=kaneo-cli,kaneo-mcp,your-client-id
1818+```
1919+2020+## Environment
2121+2222+| Variable | Description |
2323+|----------|-------------|
2424+| `KANEO_API_URL` | Kaneo API origin (default `http://localhost:1337`). Do not include `/api`. |
2525+| `KANEO_MCP_CLIENT_ID` | Device-flow client id (default `kaneo-mcp`). Must match `DEVICE_AUTH_CLIENT_IDS` on the server. |
2626+2727+## Install
2828+2929+**Recommended (no global install):** run the interactive installer with npx:
3030+3131+```bash
3232+npx @kaneo/mcp
3333+```
3434+3535+npm downloads the package, then an **interactive menu** (arrow keys + Enter) asks **where** to register the server (Cursor user-wide, Cursor project, Claude Desktop, or a custom JSON path). It then merges a `mcpServers` entry that points at this package’s `dist/index.js` with your current Node binary.
3636+3737+In a normal terminal, `npx @kaneo/mcp` and `kaneo-mcp` with no subcommand both start the installer. When the process is **not** attached to a TTY (for example when Cursor launches the MCP server with a pipe), the same entry runs the stdio MCP server instead.
3838+3939+To run the server manually from a shell (for example to debug stdio), use:
4040+4141+```bash
4242+npx @kaneo/mcp serve
4343+```
4444+4545+If you prefer a global install:
4646+4747+```bash
4848+npm install -g @kaneo/mcp
4949+kaneo-mcp
5050+```
5151+5252+(`kaneo-mcp install` is the same installer with an explicit subcommand.)
5353+5454+Non-interactive example (Cursor user config, skip overwrite prompts):
5555+5656+```bash
5757+kaneo-mcp install --target cursor-user -y
5858+```
5959+6060+Point at a self-hosted API when generating the config:
6161+6262+```bash
6363+kaneo-mcp install --target cursor-user -y --api-url https://kaneo.example.com
6464+```
6565+6666+See all options:
6767+6868+```bash
6969+kaneo-mcp install --help
7070+```
7171+7272+If you are currently inside the local `packages/mcp` package directory, npm may resolve the local workspace package instead of the published one and fail to expose the bin. In that case, either run `npx` from outside `packages/mcp`, or use a local build:
7373+7474+```bash
7575+node dist/index.js
7676+```
7777+7878+The published package includes `dist/`. `prepublishOnly` runs the build before publish.
7979+8080+## Develop from source
8181+8282+From the repo root:
8383+8484+```bash
8585+pnpm install
8686+pnpm --filter @kaneo/mcp run build
8787+pnpm --filter @kaneo/mcp run start
8888+pnpm --filter @kaneo/mcp run test
8989+```
9090+9191+Or run it from the package directory:
9292+9393+```bash
9494+pnpm -C packages/mcp run build
9595+```
9696+9797+The CLI entry points to `./dist/index.js`. Use `npx @kaneo/mcp` or `kaneo-mcp` after a global install so your IDE config points at the resolved path.
9898+9999+## Authentication
100100+101101+On the first tool call that needs Kaneo, the server:
102102+103103+1. Requests a device code from `POST /api/auth/device/code`
104104+2. Prints the verification URL and user code to `stderr`
105105+3. Tries to open the browser
106106+4. Polls `POST /api/auth/device/token` until approved
107107+5. Stores the access token at `~/.config/kaneo-mcp/credentials.json` with mode `0600`
108108+109109+## Tools
110110+111111+- Session: `whoami`, `list_workspaces`
112112+- Projects: `list_projects`, `get_project`, `create_project`, `update_project`
113113+- Tasks: `list_tasks`, `get_task`, `create_task`, `update_task`, `move_task`, `update_task_status`
114114+- Comments: `list_task_comments`, `create_task_comment`
115115+- Labels: `list_workspace_labels`, `create_label`, `attach_label_to_task`, `detach_label_from_task`
···11+import { stdin as input } from "node:process";
22+import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
33+import { runInstall } from "./install/index.js";
44+import { createMcpServer } from "./server.js";
55+66+const SERVE_ALIASES = new Set(["serve", "server", "stdio", "run"]);
77+88+export async function runCli(): Promise<void> {
99+ const argv = process.argv.slice(2);
1010+ if (argv[0] === "-h" || argv[0] === "--help" || argv[0] === "help") {
1111+ printMainHelp();
1212+ return;
1313+ }
1414+ if (argv[0] === "install" || argv[0] === "setup") {
1515+ await runInstall(argv.slice(1));
1616+ return;
1717+ }
1818+ if (argv[0] !== undefined) {
1919+ if (SERVE_ALIASES.has(argv[0])) {
2020+ await startMcpServer();
2121+ return;
2222+ }
2323+ console.error(`Unknown command: ${argv[0]}`);
2424+ printMainHelp();
2525+ process.exitCode = 1;
2626+ return;
2727+ }
2828+ if (input.isTTY) {
2929+ await runInstall([]);
3030+ return;
3131+ }
3232+ await startMcpServer();
3333+}
3434+3535+async function startMcpServer(): Promise<void> {
3636+ const server = createMcpServer();
3737+ const transport = new StdioServerTransport();
3838+ await server.connect(transport);
3939+}
4040+4141+function printMainHelp(): void {
4242+ console.log(`kaneo-mcp — Kaneo MCP server (stdio transport)
4343+4444+Usage:
4545+ npx @kaneo/mcp Interactive installer (terminal only; no global install)
4646+ kaneo-mcp Same: installer in a TTY; MCP server when stdin is piped
4747+ kaneo-mcp install Register in Cursor / Claude / a custom path (explicit)
4848+ kaneo-mcp serve Run the MCP server (use from a terminal to test stdio)
4949+ kaneo-mcp help
5050+5151+Options:
5252+ -h, --help Show this help
5353+5454+MCP clients (Cursor, etc.) run this process with a pipe, so they get the server.
5555+In a normal terminal, the default is the interactive installer.
5656+5757+See also: kaneo-mcp install --help
5858+`);
5959+}