npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@osiris-ai/linear-sdk

v0.1.1

Published

Osiris Linear SDK

Readme

@osiris-ai/linear-sdk

OAuth 2.0 Linear authenticator for building authenticated MCPs with Linear project management integration.

npm version License: MIT

Overview

The Linear SDK provides seamless OAuth 2.0 authentication for Linear in the Osiris ecosystem. Build powerful MCPs (Model Context Protocol) that can interact with Linear issues, projects, teams, and workflows with enterprise-grade security and zero-configuration authentication.

Key Features:

  • 🔐 Zero-config OAuth - No client credentials or setup required
  • 📊 GraphQL API - Full access to Linear's GraphQL API
  • 🏢 Organization Support - Multi-organization workspace access
  • 🔄 Auto Token Refresh - Automatic token lifecycle management
  • 🛡️ Enterprise Security - Built on Osiris Hub authentication
  • 📝 Full TypeScript - Complete type safety and IDE support
  • 🔑 Dual Auth Modes - Both OAuth and API key authentication

Installation

npm install @osiris-ai/linear-sdk @osiris-ai/sdk

Quick Start

Hub Authentication (Recommended)

The Linear authenticator works automatically through the Osiris Hub - no Linear OAuth app setup required.

import { createMcpServer, getAuthContext } from '@osiris-ai/sdk';
import { createSuccessResponse, createErrorResponse } from '../utils/types.js';
import { z } from 'zod';

await createMcpServer({
  name: 'linear-mcp',
  version: '1.0.0',
  auth: {
    useHub: true,
    hubConfig: {
      baseUrl: process.env.HUB_BASE_URL!,
      clientId: process.env.OAUTH_CLIENT_ID!,
      clientSecret: process.env.OAUTH_CLIENT_SECRET!,
    }
  },
  configure: (server) => {
    // Create Linear issue
    server.tool(
      'create_linear_issue',
      'Create a new Linear issue',
      {
        title: z.string(),
        description: z.string(),
        teamId: z.string(),
        priority: z.number().min(0).max(4).optional()
      },
      async ({ title, description, teamId, priority }) => {
        try {
          const { token, context } = getAuthContext("osiris");
          if (!token || !context) {
            return createErrorResponse("User not authenticated");
          }

          // GraphQL mutation to create issue
          const mutation = `
            mutation CreateIssue($input: IssueCreateInput!) {
              issueCreate(input: $input) {
                success
                issue {
                  id
                  title
                  url
                  identifier
                }
              }
            }
          `;

          const response = await fetch(`https://api.osirislabs.xyz/v1/hub/action/${context.deploymentId}/linear/graphql`, {
            method: 'POST',
            headers: {
              'Authorization': `Bearer ${token.access_token}`,
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              query: mutation,
              variables: {
                input: { title, description, teamId, priority }
              }
            })
          });

          const result = await response.json();
          
          if (result.data?.issueCreate?.success) {
            const issue = result.data.issueCreate.issue;
            return createSuccessResponse('Issue created successfully', {
              issueId: issue.id,
              identifier: issue.identifier,
              url: issue.url
            });
          } else {
            return createErrorResponse('Failed to create issue');
          }
        } catch (error) {
          return createErrorResponse(error);
        }
      }
    );
  }
});

Available Linear Scopes

Configure your MCP to request specific Linear permissions:

All slack scopes are supported and they all need to prefixed with linear:

Local Authentication (Advanced)

For custom authentication flows or enterprise requirements:

import { LinearAuthenticator } from '@osiris-ai/linear-sdk';
import { createMcpServer } from '@osiris-ai/sdk';

const linearAuth = new LinearAuthenticator(
  ['read', 'write', 'issues:write'],
  {
    clientId: process.env.LINEAR_CLIENT_ID!,
    clientSecret: process.env.LINEAR_CLIENT_SECRET!,
    redirectUri: 'http://localhost:3000/linear/callback',
    apiKey: process.env.LINEAR_API_KEY // Optional: for API key mode
  }
);

await createMcpServer({
  name: 'linear-mcp',
  version: '1.0.0',
  auth: {
    useHub: false,
    directAuth: {
      linear: linearAuth
    }
  },
  configure: (server) => {
    // Your Linear tools here
  }
});

API Reference

LinearAuthenticator

The main authenticator class for Linear OAuth integration.

class LinearAuthenticator extends OAuthAuthenticator<LinearCallbackParams, LinearTokenResponse>

Constructor

new LinearAuthenticator(allowedScopes: string[], config: LinearAuthenticatorConfig)

Parameters:

  • allowedScopes: Array of Linear OAuth scopes your MCP requires
  • config: Linear OAuth application configuration

Methods

getAuthenticationURL(scopes: string[], options: AuthenticationURLOptions): string

Generate Linear OAuth authorization URL with actor support.

callback(params: LinearCallbackParams): Promise<LinearTokenResponse>

Handle OAuth callback and exchange code for tokens.

refreshToken(refreshToken: string): Promise<LinearTokenResponse>

Refresh an expired access token.

getUserInfo(accessToken: string): Promise<LinearUserInfo>

Get authenticated user information via GraphQL.

action(params: ActionParams, accessToken: string, refreshToken?: string): Promise<ActionResponse>

Execute Linear GraphQL operations with automatic token refresh.

Error Handling

The Linear authenticator provides robust error handling with automatic retries and detailed error messages:

server.tool('resilient_linear_tool', 'Linear tool with error handling', schema, async (params) => {
  try {
    const { token, context } = getAuthContext("osiris");
    if (!token || !context) {
      return createErrorResponse("🔐 Please connect your Linear account first");
    }

    const query = `
      query {
        viewer {
          id
          name
          organization {
            name
          }
        }
      }
    `;

    const response = await fetch(`https://api.osirislabs.xyz/v1/hub/action/${context.deploymentId}/linear/graphql`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token.access_token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ query })
    });

    if (!response.ok) {
      if (response.status === 401) {
        return createErrorResponse("❌ Linear authentication expired. Please reconnect your account.");
      }
      if (response.status === 403) {
        return createErrorResponse("❌ Insufficient Linear permissions. Please grant additional scopes.");
      }
      return createErrorResponse(`Linear API error: ${response.statusText}`);
    }

    const result = await response.json();
    if (result.errors) {
      return createErrorResponse(`GraphQL errors: ${result.errors.map(e => e.message).join(', ')}`);
    }

    return createSuccessResponse('Linear data retrieved', result.data);
  } catch (error: any) {
    return createErrorResponse(`Linear error: ${error.message}`);
  }
});

Getting Started

  1. Install the Osiris CLI:

    npm install -g @osiris-ai/cli
  2. Set up authentication:

    npx @osiris-ai/cli register
    npx @osiris-ai/cli create-client
    npx @osiris-ai/cli connect-auth
  3. Create your Linear MCP:

    npx @osiris-ai/cli create-mcp my-linear-mcp
  4. Add Linear integration:

    npm install @osiris-ai/linear-sdk

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Support

License

MIT License - see LICENSE file for details.


Built with ❤️ by the Osiris Labs team.