Building GitHub MCP Server for Cursor IDE Integration

4 min readSargon Piraev

Learn how to build a production-ready MCP server that integrates GitHub API with Cursor IDE for seamless workflow automation

Motivation

I absolutely love using Cursor IDE for all my development work. As someone who works extensively with GitHub for both personal and professional projects, I wanted to bring GitHub's powerful API capabilities directly into my Cursor workflow. Building an MCP server felt like the perfect way to achieve this while also getting hands-on experience with the MCP protocol. This project lets me access GitHub data and operations right from Cursor's command palette, making my development process much more streamlined.

Implementation

Let's walk through building a GitHub MCP server step by step. We'll create a server that can interact with GitHub's REST API v3 and expose its functionality through MCP tools.

Project Structure

First, let's set up our project structure:

mkdir github-mcp-server
cd github-mcp-server
npm init -y

# Create the basic file structure
mkdir src
touch src/server.ts src/main.ts

Install Dependencies

Add the required dependencies to package.json:

npm install @cursor-io/mcp-server@latest
npm install axios zod dotenv
npm install typescript @types/node --save-dev

Environment Setup

Create a .env file for GitHub authentication:

GITHUB_TOKEN=your_personal_access_token

Server Implementation

Let's implement the server in src/server.ts:

import { McpServer } from '@cursor-io/mcp-server';
import { z } from 'zod';
import axios from 'axios';
import dotenv from 'dotenv';

// Load environment variables
dotenv.config();

// Validate environment
const envSchema = z.object({
  GITHUB_TOKEN: z.string().min(1),
});

const env = envSchema.parse(process.env);

// Create GitHub API client
const githubClient = axios.create({
  baseURL: 'https://api.github.com',
  headers: {
    Authorization: `Bearer ${env.GITHUB_TOKEN}`,
    Accept: 'application/vnd.github.v3+json',
  },
});

// Create MCP server instance
export const mcpServer = new McpServer({
  name: 'github',
  version: '1.0.0',
});

// Add tools
mcpServer.tool({
  name: 'list_repos',
  description: 'List repositories for the authenticated user',
  parameters: z.object({
    per_page: z.number().optional().default(30),
    page: z.number().optional().default(1),
  }),
  handler: async (params) => {
    const response = await githubClient.get('/user/repos', {
      params: {
        per_page: params.per_page,
        page: params.page,
      },
    });
    
    return response.data.map((repo: any) => ({
      name: repo.name,
      full_name: repo.full_name,
      description: repo.description,
      url: repo.html_url,
    }));
  },
});

mcpServer.tool({
  name: 'create_issue',
  description: 'Create a new issue in a repository',
  parameters: z.object({
    owner: z.string(),
    repo: z.string(),
    title: z.string(),
    body: z.string(),
  }),
  handler: async (params) => {
    const response = await githubClient.post(
      `/repos/${params.owner}/${params.repo}/issues`,
      {
        title: params.title,
        body: params.body,
      }
    );
    
    return {
      number: response.data.number,
      url: response.data.html_url,
      title: response.data.title,
    };
  },
});

Entry Point

Create the entry point in src/main.ts:

import { mcpServer } from './server';

async function main() {
  await mcpServer.listen();
  console.log('GitHub MCP server running...');
}

main().catch(console.error);

Usage

Let's go through how to set up and use the GitHub MCP server with Cursor IDE.

Global Installation

Install the package globally:

npm install -g github-mcp-server

Configure Cursor

Add the GitHub MCP server to your Cursor configuration by editing ~/.cursor/mcp.json:

{
  "servers": [
    {
      "name": "github",
      "command": "github-mcp-server"
    }
  ]
}

Example Prompts

Here are some example prompts you can use in Cursor:

  1. List your repositories:
List my GitHub repositories and show their descriptions

Response:

Here are your GitHub repositories:

1. my-awesome-project
   Description: A collection of useful utilities
   URL: https://github.com/username/my-awesome-project

2. personal-website
   Description: My personal portfolio website
   URL: https://github.com/username/personal-website
  1. Create an issue:
Create a GitHub issue in my-awesome-project titled "Add authentication feature" with description "Implement OAuth2 authentication flow"

Response:

Created issue #42 in my-awesome-project:
Title: Add authentication feature
URL: https://github.com/username/my-awesome-project/issues/42
  1. Check repository status:
Show me the status of my latest commits in the main branch

Response:

Latest commit status for main branch:
- SHA: abc123
- Message: "Update README.md"
- Author: username
- Timestamp: 2024-01-09T10:30:00Z

How It Works

Here's a sequence diagram showing how the GitHub MCP server integrates with Cursor IDE:

Rendering diagram...

The diagram shows how user requests flow through the system, from the initial prompt in Cursor IDE through the MCP server and GitHub API, and back to the user with the results.