PromptBase
Upgrade
Close icon
General
Home
Marketplace
Create
Hire
Login
Chat
Sell
Explore

Prompt Details

Model
(claude-4-5-sonnet)
Token size
740
Example input
[INTEGRATION]: GitHub repository [TOOLS_NEEDED]: create_issue, list_issues, close_issue [AUTH_TYPE]: api_key [DEPLOYMENT]: local
Example output
## MCP Server: github-issue-manager ### Overview This MCP server connects Claude to GitHub's REST API for issue management operations. It provides three core tools for creating, listing, and closing issues in GitHub repositories. The server uses personal access token authentication and is designed for local deployment with the Claude desktop app or API integrations. ### Tools | Tool | Description | Parameters | |------|-------------|------------| | `create_issue` | Creates a new issue in a specified GitHub repository | `owner` (string), `repo` (string), `title` (string), `body` (string, optional), `labels` (array[string], optional), `assignees` (array[string], optional) | | `list_issues` | Lists issues from a GitHub repository with filtering options | `owner` (string), `repo` (string), `state` (string: "open"\|"closed"\|"all", default: "open"), `labels` (string, optional), `per_page` (int, default: 30, max: 100) | | `close_issue` | Closes an open issue in a GitHub repository | `owner` (string), `repo` (string), `issue_number` (int), `comment` (string, optional) | ### Implementation ```python import os import httpx from mcp.server.fastmcp import FastMCP from typing import Optional, Literal # Initialize FastMCP server mcp = FastMCP("github-issue-manager") # GitHub API configuration GITHUB_API_BASE = "https://api.github.com" GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") if not GITHUB_TOKEN: raise ValueError("GITHUB_TOKEN environment variable is required") # HTTP client with authentication def get_headers(): return { "Authorization": f"Bearer {GITHUB_TOKEN}", "Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28", "User-Agent": "MCP-GitHub-Issue-Manager" } @mcp.tool() async def create_issue( owner: str, repo: str, title: str, body: Optional[str] = None, labels: Optional[list[str]] = None, assignees: Optional[list[str]] = None ) -> str: """ Creates a new issue in a GitHub repository. Args: owner: Repository owner (user or organization) repo: Repository name title: Issue title (required) body: Issue description in Markdown labels: List of label names to apply assignees: List of GitHub usernames to assign Returns: JSON string with created issue details """ # Input validation if not owner or not repo or not title: return '{"error": "owner, repo, and title are required parameters"}' if len(title) > 256: return '{"error": "title exceeds 256 character limit"}' url = f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues" payload = {"title": title} if body: payload["body"] = body if labels: payload["labels"] = labels if assignees: payload["assignees"] = assignees try: async with httpx.AsyncClient(timeout=30.0) as client: response = await client.post(url, json=payload, headers=get_headers()) if response.status_code == 201: issue_data = response.json() return f'{{"success": true, "issue_number": {issue_data["number"]}, "url": "{issue_data["html_url"]}", "state": "{issue_data["state"]}"}}' elif response.status_code == 404: return '{"error": "Repository not found or token lacks access"}' elif response.status_code == 403: return '{"error": "Rate limit exceeded or insufficient permissions"}' elif response.status_code == 422: error_msg = response.json().get("message", "Validation failed") return f'{{"error": "Validation error: {error_msg}"}}' else: return f'{{"error": "GitHub API error: {response.status_code}"}}' except httpx.TimeoutException: return '{"error": "Request timed out after 30 seconds"}' except httpx.RequestError as e: return f'{{"error": "Network error: {str(e)}"}}' except Exception as e: return f'{{"error": "Unexpected error: {str(e)}"}}' @mcp.tool() async def list_issues( owner: str, repo: str, state: Literal["open", "closed", "all"] = "open", labels: Optional[str] = None, per_page: int = 30 ) -> str: """ Lists issues from a GitHub repository. Args: owner: Repository owner repo: Repository name state: Filter by state (open, closed, all) labels: Comma-separated list of label names per_page: Results per page (1-100, default 30) Returns: JSON string with issue list """ # Input validation if not owner or not repo: return '{"error": "owner and repo are required parameters"}' if per_page < 1 or per_page > 100: return '{"error": "per_page must be between 1 and 100"}' url = f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues" params = { "state": state, "per_page": per_page } if labels: params["labels"] = labels try: async with httpx.AsyncClient(timeout=30.0) as client: response = await client.get(url, params=params, headers=get_headers()) if response.status_code == 200: issues = response.json() # Filter out pull requests (GitHub API includes PRs in issues endpoint) issues = [i for i in issues if "pull_request" not in i] simplified = [{ "number": issue["number"], "title": issue["title"], "state": issue["state"], "created_at": issue["created_at"], "updated_at": issue["updated_at"], "url": issue["html_url"], "labels": [label["name"] for label in issue.get("labels", [])], "assignees": [user["login"] for user in issue.get("assignees", [])] } for issue in issues] import json return json.dumps({"success": True, "count": len(simplified), "issues": simplified}) elif response.status_code == 404: return '{"error": "Repository not found or token lacks access"}' elif response.status_code == 403: return '{"error": "Rate limit exceeded or insufficient permissions"}' else: return f'{{"error": "GitHub API error: {response.status_code}"}}' except httpx.TimeoutException: return '{"error": "Request timed out after 30 seconds"}' except httpx.RequestError as e: return f'{{"error": "Network error: {str(e)}"}}' except Exception as e: return f'{{"error": "Unexpected error: {str(e)}"}}' @mcp.tool() async def close_issue( owner: str, repo: str, issue_number: int, comment: Optional[str] = None ) -> str: """ Closes an open issue in a GitHub repository. Args: owner: Repository owner repo: Repository name issue_number: Issue number to close comment: Optional closing comment Returns: JSON string with operation result """ # Input validation if not owner or not repo or not issue_number: return '{"error": "owner, repo, and issue_number are required parameters"}' if issue_number < 1: return '{"error": "issue_number must be a positive integer"}' try: async with httpx.AsyncClient(timeout=30.0) as client: # Add comment if provided if comment: comment_url = f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues/{issue_number}/comments" comment_response = await client.post( comment_url, json={"body": comment}, headers=get_headers() ) if comment_response.status_code not in [200, 201]: return f'{{"error": "Failed to add comment: {comment_response.status_code}"}}' # Close the issue issue_url = f"{GITHUB_API_BASE}/repos/{owner}/{repo}/issues/{issue_number}" response = await client.patch( issue_url, json={"state": "closed"}, headers=get_headers() ) if response.status_code == 200: issue_data = response.json() return f'{{"success": true, "issue_number": {issue_data["number"]}, "state": "{issue_data["state"]}", "url": "{issue_data["html_url"]}"}}' elif response.status_code == 404: return '{"error": "Issue or repository not found"}' elif response.status_code == 403: return '{"error": "Rate limit exceeded or insufficient permissions"}' else: return f'{{"error": "GitHub API error: {response.status_code}"}}' except httpx.TimeoutException: return '{"error": "Request timed out after 30 seconds"}' except httpx.RequestError as e: return f'{{"error": "Network error: {str(e)}"}}' except Exception as e: return f'{{"error": "Unexpected error: {str(e)}"}}' if __name__ == "__main__": mcp.run() ``` ### Deployment **Installation:** ```bash # Create project directory mkdir github-mcp-server cd github-mcp-server # Create virtual environment python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install dependencies pip install mcp httpx # Save the server code as server.py # (paste the implementation code above) # Set your GitHub token export GITHUB_TOKEN="ghp_your_personal_access_token_here" ``` **Claude Desktop Configuration:** Edit your Claude configuration file: - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` - Windows: `%APPDATA%\Claude\claude_desktop_config.json` ```json { "mcpServers": { "github-issues": { "command": "/path/to/github-mcp-server/venv/bin/python", "args": ["/path/to/github-mcp-server/server.py"], "env": { "GITHUB_TOKEN": "ghp_your_personal_access_token_here" } } } } ``` **Testing:** ```bash # Activate virtual environment source venv/bin/activate # Run the server directly (for debugging) python server.py # The server will start and listen for MCP protocol messages ``` ### Security Considerations 1. **Token Security** - GitHub personal access token must have `repo` scope (full repository access) - Never commit tokens to version control - Store token in environment variables or secure secret management - Token should be set with minimal required permissions for production use 2. **Input Validation** - All user inputs are validated before API calls - String length limits enforced (title max 256 chars per GitHub limits) - Numeric bounds checked (per_page: 1-100, issue_number > 0) - Repository owner/name format not validated (GitHub API handles this) 3. **Rate Limiting** - GitHub API enforces rate limits: 5,000 requests/hour for authenticated requests - Server returns clear error messages on 403 rate limit responses - Consider implementing client-side retry logic with exponential backoff - No server-side rate limiting implemented (assumes single-user local deployment) 4. **Error Handling** - Network timeouts set to 30 seconds - All external API calls wrapped in try-catch - Graceful degradation with descriptive error messages - No sensitive information leaked in error responses 5. **Sandboxing** - Server only accesses GitHub API endpoints - No file system operations beyond environment variable reads - No shell command execution - Async operations prevent blocking ### Assumptions * GitHub personal access token with `repo` scope is available and valid * User has read/write access to target repositories * GitHub REST API v3 endpoints remain stable (using versioned API header 2022-11-28) * Local deployment implies single-user context (no multi-tenancy considerations) * Standard GitHub API rate limits apply (5,000 req/hour authenticated) * Pull requests are filtered out from `list_issues` results (GitHub includes PRs in issues endpoint) * Network connectivity to api.github.com is available * Python 3.10+ runtime environment
🌀 Claude

Mcp Server Architect

Add to Cart
Instant accessInstant access
Usage rightsCommercial use
Money-back guaranteeMoney‑back
By purchasing this prompt, you agree to our terms of service
CLAUDE-4-5-SONNET
Tested icon
Guide icon
4 examples icon
Free credits icon
**production-ready MCP servers** that connect AI agents (Claude / GPT / Cursor) to real tools, APIs, and data sources — with security, validation, and deployment-ready code. This is not a tutorial. It **outputs a complete MCP server implementation** based on your inputs. (Claude + ChatGPT Compatible)**
...more
Added over 1 month ago
Report
Browse Marketplace