@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.
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/sdkQuick 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 requiresconfig: 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
Install the Osiris CLI:
npm install -g @osiris-ai/cliSet up authentication:
npx @osiris-ai/cli register npx @osiris-ai/cli create-client npx @osiris-ai/cli connect-authCreate your Linear MCP:
npx @osiris-ai/cli create-mcp my-linear-mcpAdd Linear integration:
npm install @osiris-ai/linear-sdk
Contributing
We welcome contributions! Please see our Contributing Guide for details.
Support
- Documentation: https://docs.osirislabs.xyz
- GitHub Issues: https://github.com/fetcchx/osiris-ai/issues
- Discord Community: Join our Discord
License
MIT License - see LICENSE file for details.
Built with ❤️ by the Osiris Labs team.
