diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 00000000..4f687118
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,212 @@
+name: Automatic Release Creation
+
+on:
+  workflow_dispatch:
+  schedule:
+    - cron: '0 10 * * *'
+
+jobs:
+  create-metadata:
+    runs-on: ubuntu-latest
+    outputs:
+      hash: ${{ steps.last-release.outputs.hash }}
+      version: ${{ steps.create-version.outputs.version}}
+      npm_packages: ${{ steps.create-npm-packages.outputs.npm_packages}}
+      pypi_packages: ${{ steps.create-pypi-packages.outputs.pypi_packages}}
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Get last release hash
+        id: last-release
+        run: |
+          HASH=$(git rev-list --tags --max-count=1 || echo "HEAD~1")
+          echo "hash=${HASH}" >> $GITHUB_OUTPUT
+          echo "Using last release hash: ${HASH}"
+
+      - name: Install uv
+        uses: astral-sh/setup-uv@v5
+
+      - name: Create version name
+        id: create-version
+        run: |
+          VERSION=$(uv run --script scripts/release.py generate-version)
+          echo "version $VERSION"
+          echo "version=$VERSION" >> $GITHUB_OUTPUT
+
+      - name: Create notes
+        run: |
+          HASH="${{ steps.last-release.outputs.hash }}"
+          uv run --script scripts/release.py generate-notes --directory src/ $HASH > RELEASE_NOTES.md
+          cat RELEASE_NOTES.md
+
+      - name: Release notes
+        uses: actions/upload-artifact@v4
+        with:
+          name: release-notes
+          path: RELEASE_NOTES.md
+
+      - name: Create python matrix
+        id: create-pypi-packages
+        run: |
+          HASH="${{ steps.last-release.outputs.hash }}"
+          PYPI=$(uv run --script scripts/release.py generate-matrix --pypi --directory src $HASH)
+          echo "pypi_packages $PYPI"
+          echo "pypi_packages=$PYPI" >> $GITHUB_OUTPUT
+
+      - name: Create npm matrix
+        id: create-npm-packages
+        run: |
+          HASH="${{ steps.last-release.outputs.hash }}"
+          NPM=$(uv run --script scripts/release.py generate-matrix --npm --directory src $HASH)
+          echo "npm_packages $NPM"
+          echo "npm_packages=$NPM" >> $GITHUB_OUTPUT
+
+  update-packages:
+    needs: [create-metadata]
+    if: ${{ needs.create-metadata.outputs.npm_packages != '[]' || needs.create-metadata.outputs.pypi_packages != '[]' }}
+    runs-on: ubuntu-latest
+    outputs:
+      changes_made: ${{ steps.commit.outputs.changes_made }}
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          fetch-depth: 0
+
+      - name: Install uv
+        uses: astral-sh/setup-uv@v5
+
+      - name: Update packages
+        run: |
+          HASH="${{ needs.create-metadata.outputs.hash }}"
+          uv run --script scripts/release.py update-packages --directory src/ $HASH
+
+      - name: Configure git
+        run: |
+          git config --global user.name "GitHub Actions"
+          git config --global user.email "actions@github.com"
+
+      - name: Commit changes
+        id: commit
+        run: |
+          VERSION="${{ needs.create-metadata.outputs.version }}"
+          git add -u
+          if git diff-index --quiet HEAD; then
+            echo "changes_made=false" >> $GITHUB_OUTPUT
+          else
+            git commit -m 'Automatic update of packages'
+            git tag -a "$VERSION" -m "Release $VERSION"
+            git push origin "$VERSION"
+            echo "changes_made=true" >> $GITHUB_OUTPUT
+          fi
+
+  publish-pypi:
+    needs: [update-packages, create-metadata]
+    strategy:
+      fail-fast: false
+      matrix:
+        package: ${{ fromJson(needs.create-metadata.outputs.pypi_packages) }}
+    name: Build ${{ matrix.package }}
+    environment: release
+    permissions:
+      id-token: write # Required for trusted publishing
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          ref: ${{ needs.create-metadata.outputs.version }}
+
+      - name: Install uv
+        uses: astral-sh/setup-uv@v5
+
+      - name: Set up Python
+        uses: actions/setup-python@v5
+        with:
+          python-version-file: "src/${{ matrix.package }}/.python-version"
+
+      - name: Install dependencies
+        working-directory: src/${{ matrix.package }}
+        run: uv sync --frozen --all-extras --dev
+
+      - name: Run pyright
+        working-directory: src/${{ matrix.package }}
+        run: uv run --frozen pyright
+
+      - name: Build package
+        working-directory: src/${{ matrix.package }}
+        run: uv build
+
+      - name: Publish package to PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          packages-dir: src/${{ matrix.package }}/dist
+
+  publish-npm:
+    needs: [update-packages, create-metadata]
+    strategy:
+      fail-fast: false
+      matrix:
+        package: ${{ fromJson(needs.create-metadata.outputs.npm_packages) }}
+    name: Build ${{ matrix.package }}
+    environment: release
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+        with:
+          ref: ${{ needs.create-metadata.outputs.version }}
+
+      - uses: actions/setup-node@v4
+        with:
+          node-version: 22
+          cache: npm
+          registry-url: 'https://registry.npmjs.org'
+
+      - name: Install dependencies
+        working-directory: src/${{ matrix.package }}
+        run: npm ci
+
+      - name: Check if version exists on npm
+        working-directory: src/${{ matrix.package }}
+        run: |
+          VERSION=$(jq -r .version package.json)
+          if npm view --json | jq --arg version "$VERSION" '[.[]][0].versions | contains([$version])'; then
+            echo "Version $VERSION already exists on npm"
+            exit 1
+          fi
+          echo "Version $VERSION is new, proceeding with publish"
+
+      - name: Build package
+        working-directory: src/${{ matrix.package }}
+        run: npm run build
+
+      - name: Publish package
+        working-directory: src/${{ matrix.package }}
+        run: |
+          npm publish --access public
+        env:
+          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+
+  create-release:
+    needs: [update-packages, create-metadata, publish-pypi, publish-npm]
+    if: needs.update-packages.outputs.changes_made == 'true'
+    runs-on: ubuntu-latest
+    environment: release
+    permissions:
+      contents: write
+    steps:
+      - uses: actions/checkout@v4
+
+      - name: Download release notes
+        uses: actions/download-artifact@v4
+        with:
+          name: release-notes
+
+      - name: Create release
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN}}
+        run: |
+          VERSION="${{ needs.create-metadata.outputs.version }}"
+          gh release create "$VERSION" \
+            --title "Release $VERSION" \
+            --notes-file RELEASE_NOTES.md
diff --git a/scripts/release.py b/scripts/release.py
new file mode 100755
index 00000000..05d76c0a
--- /dev/null
+++ b/scripts/release.py
@@ -0,0 +1,210 @@
+#!/usr/bin/env uv run --script
+# /// script
+# requires-python = ">=3.12"
+# dependencies = [
+#     "click>=8.1.8",
+#     "tomlkit>=0.13.2"
+# ]
+# ///
+import sys
+import re
+import click
+from pathlib import Path
+import json
+import tomlkit
+import datetime
+import subprocess
+from dataclasses import dataclass
+from typing import Any, Iterator, NewType, Protocol
+
+
+Version = NewType("Version", str)
+GitHash = NewType("GitHash", str)
+
+
+class GitHashParamType(click.ParamType):
+    name = "git_hash"
+
+    def convert(
+        self, value: Any, param: click.Parameter | None, ctx: click.Context | None
+    ) -> GitHash | None:
+        if value is None:
+            return None
+
+        if not (8 <= len(value) <= 40):
+            self.fail(f"Git hash must be between 8 and 40 characters, got {len(value)}")
+
+        if not re.match(r"^[0-9a-fA-F]+$", value):
+            self.fail("Git hash must contain only hex digits (0-9, a-f)")
+
+        try:
+            # Verify hash exists in repo
+            subprocess.run(
+                ["git", "rev-parse", "--verify", value], check=True, capture_output=True
+            )
+        except subprocess.CalledProcessError:
+            self.fail(f"Git hash {value} not found in repository")
+
+        return GitHash(value.lower())
+
+
+GIT_HASH = GitHashParamType()
+
+
+class Package(Protocol):
+    path: Path
+
+    def package_name(self) -> str: ...
+
+    def update_version(self, version: Version) -> None: ...
+
+
+@dataclass
+class NpmPackage:
+    path: Path
+
+    def package_name(self) -> str:
+        with open(self.path / "package.json", "r") as f:
+            return json.load(f)["name"]
+
+    def update_version(self, version: Version):
+        with open(self.path / "package.json", "r+") as f:
+            data = json.load(f)
+            data["version"] = version
+            f.seek(0)
+            json.dump(data, f, indent=2)
+            f.truncate()
+
+
+@dataclass
+class PyPiPackage:
+    path: Path
+
+    def package_name(self) -> str:
+        with open(self.path / "pyproject.toml") as f:
+            toml_data = tomlkit.parse(f.read())
+            name = toml_data.get("project", {}).get("name")
+            if not name:
+                raise Exception("No name in pyproject.toml project section")
+            return str(name)
+
+    def update_version(self, version: Version):
+        # Update version in pyproject.toml
+        with open(self.path / "pyproject.toml") as f:
+            data = tomlkit.parse(f.read())
+            data["project"]["version"] = version
+
+        with open(self.path / "pyproject.toml", "w") as f:
+            f.write(tomlkit.dumps(data))
+
+
+def has_changes(path: Path, git_hash: GitHash) -> bool:
+    """Check if any files changed between current state and git hash"""
+    try:
+        output = subprocess.run(
+            ["git", "diff", "--name-only", git_hash, "--", "."],
+            cwd=path,
+            check=True,
+            capture_output=True,
+            text=True,
+        )
+
+        changed_files = [Path(f) for f in output.stdout.splitlines()]
+        relevant_files = [f for f in changed_files if f.suffix in [".py", ".ts"]]
+        return len(relevant_files) >= 1
+    except subprocess.CalledProcessError:
+        return False
+
+
+def gen_version() -> Version:
+    """Generate version based on current date"""
+    now = datetime.datetime.now()
+    return Version(f"{now.year}.{now.month}.{now.day}")
+
+
+def find_changed_packages(directory: Path, git_hash: GitHash) -> Iterator[Package]:
+    for path in directory.glob("*/package.json"):
+        if has_changes(path.parent, git_hash):
+            yield NpmPackage(path.parent)
+    for path in directory.glob("*/pyproject.toml"):
+        if has_changes(path.parent, git_hash):
+            yield PyPiPackage(path.parent)
+
+
+@click.group()
+def cli():
+    pass
+
+
+@cli.command("update-packages")
+@click.option(
+    "--directory", type=click.Path(exists=True, path_type=Path), default=Path.cwd()
+)
+@click.argument("git_hash", type=GIT_HASH)
+def update_packages(directory: Path, git_hash: GitHash) -> int:
+    # Detect package type
+    path = directory.resolve(strict=True)
+    version = gen_version()
+
+    for package in find_changed_packages(path, git_hash):
+        name = package.package_name()
+        package.update_version(version)
+
+        click.echo(f"{name}@{version}")
+
+    return 0
+
+
+@cli.command("generate-notes")
+@click.option(
+    "--directory", type=click.Path(exists=True, path_type=Path), default=Path.cwd()
+)
+@click.argument("git_hash", type=GIT_HASH)
+def generate_notes(directory: Path, git_hash: GitHash) -> int:
+    # Detect package type
+    path = directory.resolve(strict=True)
+    version = gen_version()
+
+    click.echo(f"# Release : v{version}")
+    click.echo("")
+    click.echo("## Updated packages")
+    for package in find_changed_packages(path, git_hash):
+        name = package.package_name()
+        click.echo(f"- {name}@{version}")
+
+    return 0
+
+
+@cli.command("generate-version")
+def generate_version() -> int:
+    # Detect package type
+    click.echo(gen_version())
+    return 0
+
+
+@cli.command("generate-matrix")
+@click.option(
+    "--directory", type=click.Path(exists=True, path_type=Path), default=Path.cwd()
+)
+@click.option("--npm", is_flag=True, default=False)
+@click.option("--pypi", is_flag=True, default=False)
+@click.argument("git_hash", type=GIT_HASH)
+def generate_matrix(directory: Path, git_hash: GitHash, pypi: bool, npm: bool) -> int:
+    # Detect package type
+    path = directory.resolve(strict=True)
+    version = gen_version()
+
+    changes = []
+    for package in find_changed_packages(path, git_hash):
+        pkg = package.path.relative_to(path)
+        if npm and isinstance(package, NpmPackage):
+            changes.append(str(pkg))
+        if pypi and isinstance(package, PyPiPackage):
+            changes.append(str(pkg))
+
+    click.echo(json.dumps(changes))
+    return 0
+
+
+if __name__ == "__main__":
+    sys.exit(cli())
diff --git a/src/github/README.md b/src/github/README.md
index d2277ab0..e06bf14a 100644
--- a/src/github/README.md
+++ b/src/github/README.md
@@ -188,6 +188,95 @@ MCP Server for the GitHub API, enabling file operations, repository management,
      - `issue_number` (number): Issue number to retrieve
    - Returns: Github Issue object & details
 
+18. `get_pull_request`
+   - Get details of a specific pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+   - Returns: Pull request details including diff and review status
+
+19. `list_pull_requests`
+   - List and filter repository pull requests
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `state` (optional string): Filter by state ('open', 'closed', 'all')
+     - `head` (optional string): Filter by head user/org and branch
+     - `base` (optional string): Filter by base branch
+     - `sort` (optional string): Sort by ('created', 'updated', 'popularity', 'long-running')
+     - `direction` (optional string): Sort direction ('asc', 'desc')
+     - `per_page` (optional number): Results per page (max 100)
+     - `page` (optional number): Page number
+   - Returns: Array of pull request details
+
+20. `create_pull_request_review`
+   - Create a review on a pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+     - `body` (string): Review comment text
+     - `event` (string): Review action ('APPROVE', 'REQUEST_CHANGES', 'COMMENT')
+     - `commit_id` (optional string): SHA of commit to review
+     - `comments` (optional array): Line-specific comments, each with:
+       - `path` (string): File path
+       - `position` (number): Line position in diff
+       - `body` (string): Comment text
+   - Returns: Created review details
+
+21. `merge_pull_request`
+   - Merge a pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+     - `commit_title` (optional string): Title for merge commit
+     - `commit_message` (optional string): Extra detail for merge commit
+     - `merge_method` (optional string): Merge method ('merge', 'squash', 'rebase')
+   - Returns: Merge result details
+
+22. `get_pull_request_files`
+   - Get the list of files changed in a pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+   - Returns: Array of changed files with patch and status details
+
+23. `get_pull_request_status`
+   - Get the combined status of all status checks for a pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+   - Returns: Combined status check results and individual check details
+
+24. `update_pull_request_branch`
+   - Update a pull request branch with the latest changes from the base branch (equivalent to GitHub's "Update branch" button)
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+     - `expected_head_sha` (optional string): The expected SHA of the pull request's HEAD ref
+   - Returns: Success message when branch is updated
+
+25. `get_pull_request_comments`
+   - Get the review comments on a pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+   - Returns: Array of pull request review comments with details like the comment text, author, and location in the diff
+
+26. `get_pull_request_reviews`
+   - Get the reviews on a pull request
+   - Inputs:
+     - `owner` (string): Repository owner
+     - `repo` (string): Repository name
+     - `pull_number` (number): Pull request number
+   - Returns: Array of pull request reviews with details like the review state (APPROVED, CHANGES_REQUESTED, etc.), reviewer, and review body
+
 ## Search Query Syntax
 
 ### Code Search
diff --git a/src/github/common/errors.ts b/src/github/common/errors.ts
new file mode 100644
index 00000000..5b940f3b
--- /dev/null
+++ b/src/github/common/errors.ts
@@ -0,0 +1,89 @@
+export class GitHubError extends Error {
+  constructor(
+    message: string,
+    public readonly status: number,
+    public readonly response: unknown
+  ) {
+    super(message);
+    this.name = "GitHubError";
+  }
+}
+
+export class GitHubValidationError extends GitHubError {
+  constructor(message: string, status: number, response: unknown) {
+    super(message, status, response);
+    this.name = "GitHubValidationError";
+  }
+}
+
+export class GitHubResourceNotFoundError extends GitHubError {
+  constructor(resource: string) {
+    super(`Resource not found: ${resource}`, 404, { message: `${resource} not found` });
+    this.name = "GitHubResourceNotFoundError";
+  }
+}
+
+export class GitHubAuthenticationError extends GitHubError {
+  constructor(message = "Authentication failed") {
+    super(message, 401, { message });
+    this.name = "GitHubAuthenticationError";
+  }
+}
+
+export class GitHubPermissionError extends GitHubError {
+  constructor(message = "Insufficient permissions") {
+    super(message, 403, { message });
+    this.name = "GitHubPermissionError";
+  }
+}
+
+export class GitHubRateLimitError extends GitHubError {
+  constructor(
+    message = "Rate limit exceeded",
+    public readonly resetAt: Date
+  ) {
+    super(message, 429, { message, reset_at: resetAt.toISOString() });
+    this.name = "GitHubRateLimitError";
+  }
+}
+
+export class GitHubConflictError extends GitHubError {
+  constructor(message: string) {
+    super(message, 409, { message });
+    this.name = "GitHubConflictError";
+  }
+}
+
+export function isGitHubError(error: unknown): error is GitHubError {
+  return error instanceof GitHubError;
+}
+
+export function createGitHubError(status: number, response: any): GitHubError {
+  switch (status) {
+    case 401:
+      return new GitHubAuthenticationError(response?.message);
+    case 403:
+      return new GitHubPermissionError(response?.message);
+    case 404:
+      return new GitHubResourceNotFoundError(response?.message || "Resource");
+    case 409:
+      return new GitHubConflictError(response?.message || "Conflict occurred");
+    case 422:
+      return new GitHubValidationError(
+        response?.message || "Validation failed",
+        status,
+        response
+      );
+    case 429:
+      return new GitHubRateLimitError(
+        response?.message,
+        new Date(response?.reset_at || Date.now() + 60000)
+      );
+    default:
+      return new GitHubError(
+        response?.message || "GitHub API error",
+        status,
+        response
+      );
+  }
+}
\ No newline at end of file
diff --git a/src/github/common/types.ts b/src/github/common/types.ts
new file mode 100644
index 00000000..cca961ba
--- /dev/null
+++ b/src/github/common/types.ts
@@ -0,0 +1,259 @@
+import { z } from "zod";
+
+// Base schemas for common types
+export const GitHubAuthorSchema = z.object({
+  name: z.string(),
+  email: z.string(),
+  date: z.string(),
+});
+
+export const GitHubOwnerSchema = z.object({
+  login: z.string(),
+  id: z.number(),
+  node_id: z.string(),
+  avatar_url: z.string(),
+  url: z.string(),
+  html_url: z.string(),
+  type: z.string(),
+});
+
+export const GitHubRepositorySchema = z.object({
+  id: z.number(),
+  node_id: z.string(),
+  name: z.string(),
+  full_name: z.string(),
+  private: z.boolean(),
+  owner: GitHubOwnerSchema,
+  html_url: z.string(),
+  description: z.string().nullable(),
+  fork: z.boolean(),
+  url: z.string(),
+  created_at: z.string(),
+  updated_at: z.string(),
+  pushed_at: z.string(),
+  git_url: z.string(),
+  ssh_url: z.string(),
+  clone_url: z.string(),
+  default_branch: z.string(),
+});
+
+export const GithubFileContentLinks = z.object({
+  self: z.string(),
+  git: z.string().nullable(),
+  html: z.string().nullable()
+});
+
+export const GitHubFileContentSchema = z.object({
+  name: z.string(),
+  path: z.string(),
+  sha: z.string(),
+  size: z.number(),
+  url: z.string(),
+  html_url: z.string(),
+  git_url: z.string(),
+  download_url: z.string(),
+  type: z.string(),
+  content: z.string().optional(),
+  encoding: z.string().optional(),
+  _links: GithubFileContentLinks
+});
+
+export const GitHubDirectoryContentSchema = z.object({
+  type: z.string(),
+  size: z.number(),
+  name: z.string(),
+  path: z.string(),
+  sha: z.string(),
+  url: z.string(),
+  git_url: z.string(),
+  html_url: z.string(),
+  download_url: z.string().nullable(),
+});
+
+export const GitHubContentSchema = z.union([
+  GitHubFileContentSchema,
+  z.array(GitHubDirectoryContentSchema),
+]);
+
+export const GitHubTreeEntrySchema = z.object({
+  path: z.string(),
+  mode: z.enum(["100644", "100755", "040000", "160000", "120000"]),
+  type: z.enum(["blob", "tree", "commit"]),
+  size: z.number().optional(),
+  sha: z.string(),
+  url: z.string(),
+});
+
+export const GitHubTreeSchema = z.object({
+  sha: z.string(),
+  url: z.string(),
+  tree: z.array(GitHubTreeEntrySchema),
+  truncated: z.boolean(),
+});
+
+export const GitHubCommitSchema = z.object({
+  sha: z.string(),
+  node_id: z.string(),
+  url: z.string(),
+  author: GitHubAuthorSchema,
+  committer: GitHubAuthorSchema,
+  message: z.string(),
+  tree: z.object({
+    sha: z.string(),
+    url: z.string(),
+  }),
+  parents: z.array(
+    z.object({
+      sha: z.string(),
+      url: z.string(),
+    })
+  ),
+});
+
+export const GitHubListCommitsSchema = z.array(z.object({
+  sha: z.string(),
+  node_id: z.string(),
+  commit: z.object({
+    author: GitHubAuthorSchema,
+    committer: GitHubAuthorSchema,
+    message: z.string(),
+    tree: z.object({
+      sha: z.string(),
+      url: z.string()
+    }),
+    url: z.string(),
+    comment_count: z.number(),
+  }),
+  url: z.string(),
+  html_url: z.string(),
+  comments_url: z.string()
+}));
+
+export const GitHubReferenceSchema = z.object({
+  ref: z.string(),
+  node_id: z.string(),
+  url: z.string(),
+  object: z.object({
+    sha: z.string(),
+    type: z.string(),
+    url: z.string(),
+  }),
+});
+
+// User and assignee schemas
+export const GitHubIssueAssigneeSchema = z.object({
+  login: z.string(),
+  id: z.number(),
+  avatar_url: z.string(),
+  url: z.string(),
+  html_url: z.string(),
+});
+
+// Issue-related schemas
+export const GitHubLabelSchema = z.object({
+  id: z.number(),
+  node_id: z.string(),
+  url: z.string(),
+  name: z.string(),
+  color: z.string(),
+  default: z.boolean(),
+  description: z.string().optional(),
+});
+
+export const GitHubMilestoneSchema = z.object({
+  url: z.string(),
+  html_url: z.string(),
+  labels_url: z.string(),
+  id: z.number(),
+  node_id: z.string(),
+  number: z.number(),
+  title: z.string(),
+  description: z.string(),
+  state: z.string(),
+});
+
+export const GitHubIssueSchema = z.object({
+  url: z.string(),
+  repository_url: z.string(),
+  labels_url: z.string(),
+  comments_url: z.string(),
+  events_url: z.string(),
+  html_url: z.string(),
+  id: z.number(),
+  node_id: z.string(),
+  number: z.number(),
+  title: z.string(),
+  user: GitHubIssueAssigneeSchema,
+  labels: z.array(GitHubLabelSchema),
+  state: z.string(),
+  locked: z.boolean(),
+  assignee: GitHubIssueAssigneeSchema.nullable(),
+  assignees: z.array(GitHubIssueAssigneeSchema),
+  milestone: GitHubMilestoneSchema.nullable(),
+  comments: z.number(),
+  created_at: z.string(),
+  updated_at: z.string(),
+  closed_at: z.string().nullable(),
+  body: z.string().nullable(),
+});
+
+// Search-related schemas
+export const GitHubSearchResponseSchema = z.object({
+  total_count: z.number(),
+  incomplete_results: z.boolean(),
+  items: z.array(GitHubRepositorySchema),
+});
+
+// Pull request schemas
+export const GitHubPullRequestRefSchema = z.object({
+  label: z.string(),
+  ref: z.string(),
+  sha: z.string(),
+  user: GitHubIssueAssigneeSchema,
+  repo: GitHubRepositorySchema,
+});
+
+export const GitHubPullRequestSchema = z.object({
+  url: z.string(),
+  id: z.number(),
+  node_id: z.string(),
+  html_url: z.string(),
+  diff_url: z.string(),
+  patch_url: z.string(),
+  issue_url: z.string(),
+  number: z.number(),
+  state: z.string(),
+  locked: z.boolean(),
+  title: z.string(),
+  user: GitHubIssueAssigneeSchema,
+  body: z.string().nullable(),
+  created_at: z.string(),
+  updated_at: z.string(),
+  closed_at: z.string().nullable(),
+  merged_at: z.string().nullable(),
+  merge_commit_sha: z.string().nullable(),
+  assignee: GitHubIssueAssigneeSchema.nullable(),
+  assignees: z.array(GitHubIssueAssigneeSchema),
+  requested_reviewers: z.array(GitHubIssueAssigneeSchema),
+  labels: z.array(GitHubLabelSchema),
+  head: GitHubPullRequestRefSchema,
+  base: GitHubPullRequestRefSchema,
+});
+
+// Export types
+export type GitHubAuthor = z.infer<typeof GitHubAuthorSchema>;
+export type GitHubRepository = z.infer<typeof GitHubRepositorySchema>;
+export type GitHubFileContent = z.infer<typeof GitHubFileContentSchema>;
+export type GitHubDirectoryContent = z.infer<typeof GitHubDirectoryContentSchema>;
+export type GitHubContent = z.infer<typeof GitHubContentSchema>;
+export type GitHubTree = z.infer<typeof GitHubTreeSchema>;
+export type GitHubCommit = z.infer<typeof GitHubCommitSchema>;
+export type GitHubListCommits = z.infer<typeof GitHubListCommitsSchema>;
+export type GitHubReference = z.infer<typeof GitHubReferenceSchema>;
+export type GitHubIssueAssignee = z.infer<typeof GitHubIssueAssigneeSchema>;
+export type GitHubLabel = z.infer<typeof GitHubLabelSchema>;
+export type GitHubMilestone = z.infer<typeof GitHubMilestoneSchema>;
+export type GitHubIssue = z.infer<typeof GitHubIssueSchema>;
+export type GitHubSearchResponse = z.infer<typeof GitHubSearchResponseSchema>;
+export type GitHubPullRequest = z.infer<typeof GitHubPullRequestSchema>;
+export type GitHubPullRequestRef = z.infer<typeof GitHubPullRequestRefSchema>;
\ No newline at end of file
diff --git a/src/github/common/utils.ts b/src/github/common/utils.ts
new file mode 100644
index 00000000..21c8aa71
--- /dev/null
+++ b/src/github/common/utils.ts
@@ -0,0 +1,133 @@
+import { createGitHubError } from "./errors.js";
+
+type RequestOptions = {
+  method?: string;
+  body?: unknown;
+  headers?: Record<string, string>;
+};
+
+async function parseResponseBody(response: Response): Promise<unknown> {
+  const contentType = response.headers.get("content-type");
+  if (contentType?.includes("application/json")) {
+    return response.json();
+  }
+  return response.text();
+}
+
+export function buildUrl(baseUrl: string, params: Record<string, string | number | undefined>): string {
+  const url = new URL(baseUrl);
+  Object.entries(params).forEach(([key, value]) => {
+    if (value !== undefined) {
+      url.searchParams.append(key, value.toString());
+    }
+  });
+  return url.toString();
+}
+
+export async function githubRequest(
+  url: string,
+  options: RequestOptions = {}
+): Promise<unknown> {
+  const headers: Record<string, string> = {
+    "Accept": "application/vnd.github.v3+json",
+    "Content-Type": "application/json",
+    ...options.headers,
+  };
+
+  if (process.env.GITHUB_PERSONAL_ACCESS_TOKEN) {
+    headers["Authorization"] = `Bearer ${process.env.GITHUB_PERSONAL_ACCESS_TOKEN}`;
+  }
+
+  const response = await fetch(url, {
+    method: options.method || "GET",
+    headers,
+    body: options.body ? JSON.stringify(options.body) : undefined,
+  });
+
+  const responseBody = await parseResponseBody(response);
+
+  if (!response.ok) {
+    throw createGitHubError(response.status, responseBody);
+  }
+
+  return responseBody;
+}
+
+export function validateBranchName(branch: string): string {
+  const sanitized = branch.trim();
+  if (!sanitized) {
+    throw new Error("Branch name cannot be empty");
+  }
+  if (sanitized.includes("..")) {
+    throw new Error("Branch name cannot contain '..'");
+  }
+  if (/[\s~^:?*[\\\]]/.test(sanitized)) {
+    throw new Error("Branch name contains invalid characters");
+  }
+  if (sanitized.startsWith("/") || sanitized.endsWith("/")) {
+    throw new Error("Branch name cannot start or end with '/'");
+  }
+  if (sanitized.endsWith(".lock")) {
+    throw new Error("Branch name cannot end with '.lock'");
+  }
+  return sanitized;
+}
+
+export function validateRepositoryName(name: string): string {
+  const sanitized = name.trim().toLowerCase();
+  if (!sanitized) {
+    throw new Error("Repository name cannot be empty");
+  }
+  if (!/^[a-z0-9_.-]+$/.test(sanitized)) {
+    throw new Error(
+      "Repository name can only contain lowercase letters, numbers, hyphens, periods, and underscores"
+    );
+  }
+  if (sanitized.startsWith(".") || sanitized.endsWith(".")) {
+    throw new Error("Repository name cannot start or end with a period");
+  }
+  return sanitized;
+}
+
+export function validateOwnerName(owner: string): string {
+  const sanitized = owner.trim().toLowerCase();
+  if (!sanitized) {
+    throw new Error("Owner name cannot be empty");
+  }
+  if (!/^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){0,38}$/.test(sanitized)) {
+    throw new Error(
+      "Owner name must start with a letter or number and can contain up to 39 characters"
+    );
+  }
+  return sanitized;
+}
+
+export async function checkBranchExists(
+  owner: string,
+  repo: string,
+  branch: string
+): Promise<boolean> {
+  try {
+    await githubRequest(
+      `https://api.github.com/repos/${owner}/${repo}/branches/${branch}`
+    );
+    return true;
+  } catch (error) {
+    if (error && typeof error === "object" && "status" in error && error.status === 404) {
+      return false;
+    }
+    throw error;
+  }
+}
+
+export async function checkUserExists(username: string): Promise<boolean> {
+  try {
+    await githubRequest(`https://api.github.com/users/${username}`);
+    return true;
+  } catch (error) {
+    if (error && typeof error === "object" && "status" in error && error.status === 404) {
+      return false;
+    }
+    throw error;
+  }
+}
\ No newline at end of file
diff --git a/src/github/index.ts b/src/github/index.ts
index 3759e8b5..fd77f017 100644
--- a/src/github/index.ts
+++ b/src/github/index.ts
@@ -5,61 +5,26 @@ import {
   CallToolRequestSchema,
   ListToolsRequestSchema,
 } from "@modelcontextprotocol/sdk/types.js";
-import fetch from "node-fetch";
 import { z } from 'zod';
 import { zodToJsonSchema } from 'zod-to-json-schema';
+
+import * as repository from './operations/repository.js';
+import * as files from './operations/files.js';
+import * as issues from './operations/issues.js';
+import * as pulls from './operations/pulls.js';
+import * as branches from './operations/branches.js';
+import * as search from './operations/search.js';
+import * as commits from './operations/commits.js';
 import {
-  CreateBranchOptionsSchema,
-  CreateBranchSchema,
-  CreateIssueOptionsSchema,
-  CreateIssueSchema,
-  CreateOrUpdateFileSchema,
-  CreatePullRequestOptionsSchema,
-  CreatePullRequestSchema,
-  CreateRepositoryOptionsSchema,
-  CreateRepositorySchema,
-  ForkRepositorySchema,
-  GetFileContentsSchema,
-  GetIssueSchema,
-  GitHubCommitSchema,
-  GitHubContentSchema,
-  GitHubCreateUpdateFileResponseSchema,
-  GitHubForkSchema,
-  GitHubIssueSchema,
-  GitHubListCommits,
-  GitHubListCommitsSchema,
-  GitHubPullRequestSchema,
-  GitHubReferenceSchema,
-  GitHubRepositorySchema,
-  GitHubSearchResponseSchema,
-  GitHubTreeSchema,
-  IssueCommentSchema,
-  ListCommitsSchema,
-  ListIssuesOptionsSchema,
-  PushFilesSchema,
-  SearchCodeResponseSchema,
-  SearchCodeSchema,
-  SearchIssuesResponseSchema,
-  SearchIssuesSchema,
-  SearchRepositoriesSchema,
-  SearchUsersResponseSchema,
-  SearchUsersSchema,
-  UpdateIssueOptionsSchema,
-  type FileOperation,
-  type GitHubCommit,
-  type GitHubContent,
-  type GitHubCreateUpdateFileResponse,
-  type GitHubFork,
-  type GitHubIssue,
-  type GitHubPullRequest,
-  type GitHubReference,
-  type GitHubRepository,
-  type GitHubSearchResponse,
-  type GitHubTree,
-  type SearchCodeResponse,
-  type SearchIssuesResponse,
-  type SearchUsersResponse
-} from './schemas.js';
+  GitHubError,
+  GitHubValidationError,
+  GitHubResourceNotFoundError,
+  GitHubAuthenticationError,
+  GitHubPermissionError,
+  GitHubRateLimitError,
+  GitHubConflictError,
+  isGitHubError,
+} from './common/errors.js';
 
 const server = new Server(
   {
@@ -73,646 +38,27 @@ const server = new Server(
   }
 );
 
-const GITHUB_PERSONAL_ACCESS_TOKEN = process.env.GITHUB_PERSONAL_ACCESS_TOKEN;
-
-if (!GITHUB_PERSONAL_ACCESS_TOKEN) {
-  console.error("GITHUB_PERSONAL_ACCESS_TOKEN environment variable is not set");
-  process.exit(1);
-}
-
-async function forkRepository(
-  owner: string,
-  repo: string,
-  organization?: string
-): Promise<GitHubFork> {
-  const url = organization
-    ? `https://api.github.com/repos/${owner}/${repo}/forks?organization=${organization}`
-    : `https://api.github.com/repos/${owner}/${repo}/forks`;
-
-  const response = await fetch(url, {
-    method: "POST",
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-    },
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubForkSchema.parse(await response.json());
-}
-
-async function createBranch(
-  owner: string,
-  repo: string,
-  options: z.infer<typeof CreateBranchOptionsSchema>
-): Promise<GitHubReference> {
-  const fullRef = `refs/heads/${options.ref}`;
-
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/git/refs`,
-    {
-      method: "POST",
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({
-        ref: fullRef,
-        sha: options.sha,
-      }),
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubReferenceSchema.parse(await response.json());
-}
-
-async function getDefaultBranchSHA(
-  owner: string,
-  repo: string
-): Promise<string> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/main`,
-    {
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-      },
-    }
-  );
-
-  if (!response.ok) {
-    const masterResponse = await fetch(
-      `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/master`,
-      {
-        headers: {
-          Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-          Accept: "application/vnd.github.v3+json",
-          "User-Agent": "github-mcp-server",
-        },
-      }
-    );
-
-    if (!masterResponse.ok) {
-      throw new Error(
-        "Could not find default branch (tried 'main' and 'master')"
-      );
-    }
-
-    const data = GitHubReferenceSchema.parse(await masterResponse.json());
-    return data.object.sha;
-  }
-
-  const data = GitHubReferenceSchema.parse(await response.json());
-  return data.object.sha;
-}
-
-async function getFileContents(
-  owner: string,
-  repo: string,
-  path: string,
-  branch?: string
-): Promise<GitHubContent> {
-  let url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
-  if (branch) {
-    url += `?ref=${branch}`;
-  }
-
-  const response = await fetch(url, {
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-    },
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  const data = GitHubContentSchema.parse(await response.json());
-
-  // If it's a file, decode the content
-  if (!Array.isArray(data) && data.content) {
-    data.content = Buffer.from(data.content, "base64").toString("utf8");
-  }
-
-  return data;
-}
-
-async function createIssue(
-  owner: string,
-  repo: string,
-  options: z.infer<typeof CreateIssueOptionsSchema>
-): Promise<GitHubIssue> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/issues`,
-    {
-      method: "POST",
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify(options),
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubIssueSchema.parse(await response.json());
-}
-
-async function createPullRequest(
-  owner: string,
-  repo: string,
-  options: z.infer<typeof CreatePullRequestOptionsSchema>
-): Promise<GitHubPullRequest> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/pulls`,
-    {
-      method: "POST",
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify(options),
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubPullRequestSchema.parse(await response.json());
-}
-
-async function createOrUpdateFile(
-  owner: string,
-  repo: string,
-  path: string,
-  content: string,
-  message: string,
-  branch: string,
-  sha?: string
-): Promise<GitHubCreateUpdateFileResponse> {
-  const encodedContent = Buffer.from(content).toString("base64");
-
-  let currentSha = sha;
-  if (!currentSha) {
-    try {
-      const existingFile = await getFileContents(owner, repo, path, branch);
-      if (!Array.isArray(existingFile)) {
-        currentSha = existingFile.sha;
-      }
-    } catch (error) {
-      console.error(
-        "Note: File does not exist in branch, will create new file"
-      );
-    }
-  }
-
-  const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
-
-  const body = {
-    message,
-    content: encodedContent,
-    branch,
-    ...(currentSha ? { sha: currentSha } : {}),
-  };
-
-  const response = await fetch(url, {
-    method: "PUT",
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify(body),
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubCreateUpdateFileResponseSchema.parse(await response.json());
-}
-
-async function createTree(
-  owner: string,
-  repo: string,
-  files: FileOperation[],
-  baseTree?: string
-): Promise<GitHubTree> {
-  const tree = files.map((file) => ({
-    path: file.path,
-    mode: "100644" as const,
-    type: "blob" as const,
-    content: file.content,
-  }));
-
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/git/trees`,
-    {
-      method: "POST",
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({
-        tree,
-        base_tree: baseTree,
-      }),
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubTreeSchema.parse(await response.json());
-}
-
-async function createCommit(
-  owner: string,
-  repo: string,
-  message: string,
-  tree: string,
-  parents: string[]
-): Promise<GitHubCommit> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/git/commits`,
-    {
-      method: "POST",
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({
-        message,
-        tree,
-        parents,
-      }),
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubCommitSchema.parse(await response.json());
-}
-
-async function updateReference(
-  owner: string,
-  repo: string,
-  ref: string,
-  sha: string
-): Promise<GitHubReference> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/git/refs/${ref}`,
-    {
-      method: "PATCH",
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({
-        sha,
-        force: true,
-      }),
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubReferenceSchema.parse(await response.json());
-}
-
-async function pushFiles(
-  owner: string,
-  repo: string,
-  branch: string,
-  files: FileOperation[],
-  message: string
-): Promise<GitHubReference> {
-  const refResponse = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
-    {
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-      },
-    }
-  );
-
-  if (!refResponse.ok) {
-    throw new Error(`GitHub API error: ${refResponse.statusText}`);
-  }
-
-  const ref = GitHubReferenceSchema.parse(await refResponse.json());
-  const commitSha = ref.object.sha;
-
-  const tree = await createTree(owner, repo, files, commitSha);
-  const commit = await createCommit(owner, repo, message, tree.sha, [
-    commitSha,
-  ]);
-  return await updateReference(owner, repo, `heads/${branch}`, commit.sha);
-}
-
-async function searchRepositories(
-  query: string,
-  page: number = 1,
-  perPage: number = 30
-): Promise<GitHubSearchResponse> {
-  const url = new URL("https://api.github.com/search/repositories");
-  url.searchParams.append("q", query);
-  url.searchParams.append("page", page.toString());
-  url.searchParams.append("per_page", perPage.toString());
-
-  const response = await fetch(url.toString(), {
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-    },
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubSearchResponseSchema.parse(await response.json());
-}
-
-async function createRepository(
-  options: z.infer<typeof CreateRepositoryOptionsSchema>
-): Promise<GitHubRepository> {
-  const response = await fetch("https://api.github.com/user/repos", {
-    method: "POST",
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-      "Content-Type": "application/json",
-    },
-    body: JSON.stringify(options),
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubRepositorySchema.parse(await response.json());
-}
-
-async function listCommits(
-  owner: string,
-  repo: string,
-  page: number = 1,
-  perPage: number = 30,
-  sha?: string,
-): Promise<GitHubListCommits> {
-  const url = new URL(`https://api.github.com/repos/${owner}/${repo}/commits`);
-  url.searchParams.append("page", page.toString());
-  url.searchParams.append("per_page", perPage.toString());
-  if (sha) {
-    url.searchParams.append("sha", sha);
-  }
-
-  const response = await fetch(
-    url.toString(),
-    {
-      method: "GET",
-      headers: {
-        "Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        "Accept": "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json"
-      },
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubListCommitsSchema.parse(await response.json());
-}
-
-async function listIssues(
-  owner: string,
-  repo: string,
-  options: Omit<z.infer<typeof ListIssuesOptionsSchema>, 'owner' | 'repo'>
-): Promise<GitHubIssue[]> {
-  const url = new URL(`https://api.github.com/repos/${owner}/${repo}/issues`);
-
-  // Add query parameters
-  if (options.state) url.searchParams.append('state', options.state);
-  if (options.labels) url.searchParams.append('labels', options.labels.join(','));
-  if (options.sort) url.searchParams.append('sort', options.sort);
-  if (options.direction) url.searchParams.append('direction', options.direction);
-  if (options.since) url.searchParams.append('since', options.since);
-  if (options.page) url.searchParams.append('page', options.page.toString());
-  if (options.per_page) url.searchParams.append('per_page', options.per_page.toString());
-
-  const response = await fetch(url.toString(), {
-    headers: {
-      "Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      "Accept": "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server"
-    }
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return z.array(GitHubIssueSchema).parse(await response.json());
-}
-
-async function updateIssue(
-  owner: string,
-  repo: string,
-  issueNumber: number,
-  options: Omit<z.infer<typeof UpdateIssueOptionsSchema>, 'owner' | 'repo' | 'issue_number'>
-): Promise<GitHubIssue> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`,
-    {
-      method: "PATCH",
-      headers: {
-        "Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        "Accept": "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json"
-      },
-      body: JSON.stringify({
-        title: options.title,
-        body: options.body,
-        state: options.state,
-        labels: options.labels,
-        assignees: options.assignees,
-        milestone: options.milestone
-      })
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return GitHubIssueSchema.parse(await response.json());
-}
-
-async function addIssueComment(
-  owner: string,
-  repo: string,
-  issueNumber: number,
-  body: string
-): Promise<z.infer<typeof IssueCommentSchema>> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}/comments`,
-    {
-      method: "POST",
-      headers: {
-        "Authorization": `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        "Accept": "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-        "Content-Type": "application/json"
-      },
-      body: JSON.stringify({ body })
-    }
-  );
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return IssueCommentSchema.parse(await response.json());
-}
-
-async function searchCode(
-  params: z.infer<typeof SearchCodeSchema>
-): Promise<SearchCodeResponse> {
-  const url = new URL("https://api.github.com/search/code");
-  Object.entries(params).forEach(([key, value]) => {
-    if (value !== undefined && value !== null) {
-      url.searchParams.append(key, value.toString());
-    }
-  });
-
-  const response = await fetch(url.toString(), {
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-    },
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return SearchCodeResponseSchema.parse(await response.json());
-}
-
-async function searchIssues(
-  params: z.infer<typeof SearchIssuesSchema>
-): Promise<SearchIssuesResponse> {
-  const url = new URL("https://api.github.com/search/issues");
-  Object.entries(params).forEach(([key, value]) => {
-    if (value !== undefined && value !== null) {
-      url.searchParams.append(key, value.toString());
+function formatGitHubError(error: GitHubError): string {
+  let message = `GitHub API Error: ${error.message}`;
+  
+  if (error instanceof GitHubValidationError) {
+    message = `Validation Error: ${error.message}`;
+    if (error.response) {
+      message += `\nDetails: ${JSON.stringify(error.response)}`;
     }
-  });
-
-  const response = await fetch(url.toString(), {
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-    },
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return SearchIssuesResponseSchema.parse(await response.json());
-}
-
-async function searchUsers(
-  params: z.infer<typeof SearchUsersSchema>
-): Promise<SearchUsersResponse> {
-  const url = new URL("https://api.github.com/search/users");
-  Object.entries(params).forEach(([key, value]) => {
-    if (value !== undefined && value !== null) {
-      url.searchParams.append(key, value.toString());
-    }
-  });
-
-  const response = await fetch(url.toString(), {
-    headers: {
-      Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-      Accept: "application/vnd.github.v3+json",
-      "User-Agent": "github-mcp-server",
-    },
-  });
-
-  if (!response.ok) {
-    throw new Error(`GitHub API error: ${response.statusText}`);
-  }
-
-  return SearchUsersResponseSchema.parse(await response.json());
-}
-
-async function getIssue(
-  owner: string,
-  repo: string,
-  issueNumber: number
-): Promise<GitHubIssue> {
-  const response = await fetch(
-    `https://api.github.com/repos/${owner}/${repo}/issues/${issueNumber}`,
-    {
-      headers: {
-        Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-        Accept: "application/vnd.github.v3+json",
-        "User-Agent": "github-mcp-server",
-      },
-    }
-);
-
-  if (!response.ok) {
-    throw new Error(`Github API error: ${response.statusText}`);
+  } else if (error instanceof GitHubResourceNotFoundError) {
+    message = `Not Found: ${error.message}`;
+  } else if (error instanceof GitHubAuthenticationError) {
+    message = `Authentication Failed: ${error.message}`;
+  } else if (error instanceof GitHubPermissionError) {
+    message = `Permission Denied: ${error.message}`;
+  } else if (error instanceof GitHubRateLimitError) {
+    message = `Rate Limit Exceeded: ${error.message}\nResets at: ${error.resetAt.toISOString()}`;
+  } else if (error instanceof GitHubConflictError) {
+    message = `Conflict: ${error.message}`;
   }
 
-  return GitHubIssueSchema.parse(await response.json());
+  return message;
 }
 
 server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -721,91 +67,87 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
       {
         name: "create_or_update_file",
         description: "Create or update a single file in a GitHub repository",
-        inputSchema: zodToJsonSchema(CreateOrUpdateFileSchema),
+        inputSchema: zodToJsonSchema(files.CreateOrUpdateFileSchema),
       },
       {
         name: "search_repositories",
         description: "Search for GitHub repositories",
-        inputSchema: zodToJsonSchema(SearchRepositoriesSchema),
+        inputSchema: zodToJsonSchema(repository.SearchRepositoriesSchema),
       },
       {
         name: "create_repository",
         description: "Create a new GitHub repository in your account",
-        inputSchema: zodToJsonSchema(CreateRepositorySchema),
+        inputSchema: zodToJsonSchema(repository.CreateRepositoryOptionsSchema),
       },
       {
         name: "get_file_contents",
-        description:
-          "Get the contents of a file or directory from a GitHub repository",
-        inputSchema: zodToJsonSchema(GetFileContentsSchema),
+        description: "Get the contents of a file or directory from a GitHub repository",
+        inputSchema: zodToJsonSchema(files.GetFileContentsSchema),
       },
       {
         name: "push_files",
-        description:
-          "Push multiple files to a GitHub repository in a single commit",
-        inputSchema: zodToJsonSchema(PushFilesSchema),
+        description: "Push multiple files to a GitHub repository in a single commit",
+        inputSchema: zodToJsonSchema(files.PushFilesSchema),
       },
       {
         name: "create_issue",
         description: "Create a new issue in a GitHub repository",
-        inputSchema: zodToJsonSchema(CreateIssueSchema),
+        inputSchema: zodToJsonSchema(issues.CreateIssueSchema),
       },
       {
         name: "create_pull_request",
         description: "Create a new pull request in a GitHub repository",
-        inputSchema: zodToJsonSchema(CreatePullRequestSchema),
+        inputSchema: zodToJsonSchema(pulls.CreatePullRequestSchema),
       },
       {
         name: "fork_repository",
-        description:
-          "Fork a GitHub repository to your account or specified organization",
-        inputSchema: zodToJsonSchema(ForkRepositorySchema),
+        description: "Fork a GitHub repository to your account or specified organization",
+        inputSchema: zodToJsonSchema(repository.ForkRepositorySchema),
       },
       {
         name: "create_branch",
         description: "Create a new branch in a GitHub repository",
-        inputSchema: zodToJsonSchema(CreateBranchSchema),
+        inputSchema: zodToJsonSchema(branches.CreateBranchSchema),
       },
       {
         name: "list_commits",
         description: "Get list of commits of a branch in a GitHub repository",
-        inputSchema: zodToJsonSchema(ListCommitsSchema)
+        inputSchema: zodToJsonSchema(commits.ListCommitsSchema)
       },
       {
         name: "list_issues",
         description: "List issues in a GitHub repository with filtering options",
-        inputSchema: zodToJsonSchema(ListIssuesOptionsSchema)
+        inputSchema: zodToJsonSchema(issues.ListIssuesOptionsSchema)
       },
       {
         name: "update_issue",
         description: "Update an existing issue in a GitHub repository",
-        inputSchema: zodToJsonSchema(UpdateIssueOptionsSchema)
+        inputSchema: zodToJsonSchema(issues.UpdateIssueOptionsSchema)
       },
       {
         name: "add_issue_comment",
         description: "Add a comment to an existing issue",
-        inputSchema: zodToJsonSchema(IssueCommentSchema)
+        inputSchema: zodToJsonSchema(issues.IssueCommentSchema)
       },
       {
         name: "search_code",
         description: "Search for code across GitHub repositories",
-        inputSchema: zodToJsonSchema(SearchCodeSchema),
+        inputSchema: zodToJsonSchema(search.SearchCodeSchema),
       },
       {
         name: "search_issues",
-        description:
-          "Search for issues and pull requests across GitHub repositories",
-        inputSchema: zodToJsonSchema(SearchIssuesSchema),
+        description: "Search for issues and pull requests across GitHub repositories",
+        inputSchema: zodToJsonSchema(search.SearchIssuesSchema),
       },
       {
         name: "search_users",
         description: "Search for users on GitHub",
-        inputSchema: zodToJsonSchema(SearchUsersSchema),
+        inputSchema: zodToJsonSchema(search.SearchUsersSchema),
       },
       {
         name: "get_issue",
         description: "Get details of a specific issue in a GitHub repository.",
-        inputSchema: zodToJsonSchema(GetIssueSchema)
+        inputSchema: zodToJsonSchema(issues.GetIssueSchema)
       }
     ],
   };
@@ -819,55 +161,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
 
     switch (request.params.name) {
       case "fork_repository": {
-        const args = ForkRepositorySchema.parse(request.params.arguments);
-        const fork = await forkRepository(
-          args.owner,
-          args.repo,
-          args.organization
-        );
+        const args = repository.ForkRepositorySchema.parse(request.params.arguments);
+        const fork = await repository.forkRepository(args.owner, args.repo, args.organization);
         return {
           content: [{ type: "text", text: JSON.stringify(fork, null, 2) }],
         };
       }
 
       case "create_branch": {
-        const args = CreateBranchSchema.parse(request.params.arguments);
-        let sha: string;
-        if (args.from_branch) {
-          const response = await fetch(
-            `https://api.github.com/repos/${args.owner}/${args.repo}/git/refs/heads/${args.from_branch}`,
-            {
-              headers: {
-                Authorization: `token ${GITHUB_PERSONAL_ACCESS_TOKEN}`,
-                Accept: "application/vnd.github.v3+json",
-                "User-Agent": "github-mcp-server",
-              },
-            }
-          );
-
-          if (!response.ok) {
-            throw new Error(`Source branch '${args.from_branch}' not found`);
-          }
-
-          const data = GitHubReferenceSchema.parse(await response.json());
-          sha = data.object.sha;
-        } else {
-          sha = await getDefaultBranchSHA(args.owner, args.repo);
-        }
-
-        const branch = await createBranch(args.owner, args.repo, {
-          ref: args.branch,
-          sha,
-        });
-
+        const args = branches.CreateBranchSchema.parse(request.params.arguments);
+        const branch = await branches.createBranchFromRef(
+          args.owner,
+          args.repo,
+          args.branch,
+          args.from_branch
+        );
         return {
           content: [{ type: "text", text: JSON.stringify(branch, null, 2) }],
         };
       }
 
       case "search_repositories": {
-        const args = SearchRepositoriesSchema.parse(request.params.arguments);
-        const results = await searchRepositories(
+        const args = repository.SearchRepositoriesSchema.parse(request.params.arguments);
+        const results = await repository.searchRepositories(
           args.query,
           args.page,
           args.perPage
@@ -878,18 +194,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
       }
 
       case "create_repository": {
-        const args = CreateRepositorySchema.parse(request.params.arguments);
-        const repository = await createRepository(args);
+        const args = repository.CreateRepositoryOptionsSchema.parse(request.params.arguments);
+        const result = await repository.createRepository(args);
         return {
-          content: [
-            { type: "text", text: JSON.stringify(repository, null, 2) },
-          ],
+          content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
         };
       }
 
       case "get_file_contents": {
-        const args = GetFileContentsSchema.parse(request.params.arguments);
-        const contents = await getFileContents(
+        const args = files.GetFileContentsSchema.parse(request.params.arguments);
+        const contents = await files.getFileContents(
           args.owner,
           args.repo,
           args.path,
@@ -901,8 +215,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
       }
 
       case "create_or_update_file": {
-        const args = CreateOrUpdateFileSchema.parse(request.params.arguments);
-        const result = await createOrUpdateFile(
+        const args = files.CreateOrUpdateFileSchema.parse(request.params.arguments);
+        const result = await files.createOrUpdateFile(
           args.owner,
           args.repo,
           args.path,
@@ -917,8 +231,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
       }
 
       case "push_files": {
-        const args = PushFilesSchema.parse(request.params.arguments);
-        const result = await pushFiles(
+        const args = files.PushFilesSchema.parse(request.params.arguments);
+        const result = await files.pushFiles(
           args.owner,
           args.repo,
           args.branch,
@@ -931,83 +245,84 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
       }
 
       case "create_issue": {
-        const args = CreateIssueSchema.parse(request.params.arguments);
+        const args = issues.CreateIssueSchema.parse(request.params.arguments);
         const { owner, repo, ...options } = args;
-        const issue = await createIssue(owner, repo, options);
+        const issue = await issues.createIssue(owner, repo, options);
         return {
           content: [{ type: "text", text: JSON.stringify(issue, null, 2) }],
         };
       }
 
       case "create_pull_request": {
-        const args = CreatePullRequestSchema.parse(request.params.arguments);
-        const { owner, repo, ...options } = args;
-        const pullRequest = await createPullRequest(owner, repo, options);
+        const args = pulls.CreatePullRequestSchema.parse(request.params.arguments);
+        const pullRequest = await pulls.createPullRequest(args);
         return {
-          content: [
-            { type: "text", text: JSON.stringify(pullRequest, null, 2) },
-          ],
+          content: [{ type: "text", text: JSON.stringify(pullRequest, null, 2) }],
         };
       }
 
       case "search_code": {
-        const args = SearchCodeSchema.parse(request.params.arguments);
-        const results = await searchCode(args);
+        const args = search.SearchCodeSchema.parse(request.params.arguments);
+        const results = await search.searchCode(args);
         return {
           content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
         };
       }
 
       case "search_issues": {
-        const args = SearchIssuesSchema.parse(request.params.arguments);
-        const results = await searchIssues(args);
+        const args = search.SearchIssuesSchema.parse(request.params.arguments);
+        const results = await search.searchIssues(args);
         return {
           content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
         };
       }
 
       case "search_users": {
-        const args = SearchUsersSchema.parse(request.params.arguments);
-        const results = await searchUsers(args);
+        const args = search.SearchUsersSchema.parse(request.params.arguments);
+        const results = await search.searchUsers(args);
         return {
           content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
         };
       }
 
       case "list_issues": {
-        const args = ListIssuesOptionsSchema.parse(request.params.arguments);
+        const args = issues.ListIssuesOptionsSchema.parse(request.params.arguments);
         const { owner, repo, ...options } = args;
-        const issues = await listIssues(owner, repo, options);
-        return { toolResult: issues };
+        const result = await issues.listIssues(owner, repo, options);
+        return { toolResult: result };
       }
 
       case "update_issue": {
-        const args = UpdateIssueOptionsSchema.parse(request.params.arguments);
+        const args = issues.UpdateIssueOptionsSchema.parse(request.params.arguments);
         const { owner, repo, issue_number, ...options } = args;
-        const issue = await updateIssue(owner, repo, issue_number, options);
-        return { toolResult: issue };
+        const result = await issues.updateIssue(owner, repo, issue_number, options);
+        return { toolResult: result };
       }
 
       case "add_issue_comment": {
-        const args = IssueCommentSchema.parse(request.params.arguments);
+        const args = issues.IssueCommentSchema.parse(request.params.arguments);
         const { owner, repo, issue_number, body } = args;
-        const comment = await addIssueComment(owner, repo, issue_number, body);
-        return { toolResult: comment };
+        const result = await issues.addIssueComment(owner, repo, issue_number, body);
+        return { toolResult: result };
       }
 
       case "list_commits": {
-        const args = ListCommitsSchema.parse(request.params.arguments);
-        const results = await listCommits(args.owner, args.repo, args.page, args.perPage, args.sha);
-        return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] };
+        const args = commits.ListCommitsSchema.parse(request.params.arguments);
+        const results = await commits.listCommits(
+          args.owner,
+          args.repo,
+          args.page,
+          args.perPage,
+          args.sha
+        );
+        return {
+          content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
+        };
       }
 
       case "get_issue": {
-        const args = z.object({
-          owner: z.string(),
-          repo: z.string(),
-          issue_number: z.number()
-        }).parse(request.params.arguments);
-        const issue = await getIssue(args.owner, args.repo, args.issue_number);
+        const args = issues.GetIssueSchema.parse(request.params.arguments);
+        const issue = await issues.getIssue(args.owner, args.repo, args.issue_number);
         return { toolResult: issue };
       }
 
@@ -1016,14 +331,10 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
     }
   } catch (error) {
     if (error instanceof z.ZodError) {
-      throw new Error(
-        `Invalid arguments: ${error.errors
-          .map(
-            (e: z.ZodError["errors"][number]) =>
-              `${e.path.join(".")}: ${e.message}`
-          )
-          .join(", ")}`
-      );
+      throw new Error(`Invalid input: ${JSON.stringify(error.errors)}`);
+    }
+    if (isGitHubError(error)) {
+      throw new Error(formatGitHubError(error));
     }
     throw error;
   }
@@ -1038,4 +349,4 @@ async function runServer() {
 runServer().catch((error) => {
   console.error("Fatal error in main():", error);
   process.exit(1);
-});
+});
\ No newline at end of file
diff --git a/src/github/operations/branches.ts b/src/github/operations/branches.ts
new file mode 100644
index 00000000..9b7033b5
--- /dev/null
+++ b/src/github/operations/branches.ts
@@ -0,0 +1,112 @@
+import { z } from "zod";
+import { githubRequest } from "../common/utils.js";
+import { GitHubReferenceSchema } from "../common/types.js";
+
+// Schema definitions
+export const CreateBranchOptionsSchema = z.object({
+  ref: z.string(),
+  sha: z.string(),
+});
+
+export const CreateBranchSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  branch: z.string().describe("Name for the new branch"),
+  from_branch: z.string().optional().describe("Optional: source branch to create from (defaults to the repository's default branch)"),
+});
+
+// Type exports
+export type CreateBranchOptions = z.infer<typeof CreateBranchOptionsSchema>;
+
+// Function implementations
+export async function getDefaultBranchSHA(owner: string, repo: string): Promise<string> {
+  try {
+    const response = await githubRequest(
+      `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/main`
+    );
+    const data = GitHubReferenceSchema.parse(response);
+    return data.object.sha;
+  } catch (error) {
+    const masterResponse = await githubRequest(
+      `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/master`
+    );
+    if (!masterResponse) {
+      throw new Error("Could not find default branch (tried 'main' and 'master')");
+    }
+    const data = GitHubReferenceSchema.parse(masterResponse);
+    return data.object.sha;
+  }
+}
+
+export async function createBranch(
+  owner: string,
+  repo: string,
+  options: CreateBranchOptions
+): Promise<z.infer<typeof GitHubReferenceSchema>> {
+  const fullRef = `refs/heads/${options.ref}`;
+
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/refs`,
+    {
+      method: "POST",
+      body: {
+        ref: fullRef,
+        sha: options.sha,
+      },
+    }
+  );
+
+  return GitHubReferenceSchema.parse(response);
+}
+
+export async function getBranchSHA(
+  owner: string,
+  repo: string,
+  branch: string
+): Promise<string> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`
+  );
+
+  const data = GitHubReferenceSchema.parse(response);
+  return data.object.sha;
+}
+
+export async function createBranchFromRef(
+  owner: string,
+  repo: string,
+  newBranch: string,
+  fromBranch?: string
+): Promise<z.infer<typeof GitHubReferenceSchema>> {
+  let sha: string;
+  if (fromBranch) {
+    sha = await getBranchSHA(owner, repo, fromBranch);
+  } else {
+    sha = await getDefaultBranchSHA(owner, repo);
+  }
+
+  return createBranch(owner, repo, {
+    ref: newBranch,
+    sha,
+  });
+}
+
+export async function updateBranch(
+  owner: string,
+  repo: string,
+  branch: string,
+  sha: string
+): Promise<z.infer<typeof GitHubReferenceSchema>> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`,
+    {
+      method: "PATCH",
+      body: {
+        sha,
+        force: true,
+      },
+    }
+  );
+
+  return GitHubReferenceSchema.parse(response);
+}
diff --git a/src/github/operations/commits.ts b/src/github/operations/commits.ts
new file mode 100644
index 00000000..b10e1b5f
--- /dev/null
+++ b/src/github/operations/commits.ts
@@ -0,0 +1,26 @@
+import { z } from "zod";
+import { githubRequest, buildUrl } from "../common/utils.js";
+
+export const ListCommitsSchema = z.object({
+  owner: z.string(),
+  repo: z.string(),
+  sha: z.string().optional(),
+  page: z.number().optional(),
+  perPage: z.number().optional()
+});
+
+export async function listCommits(
+  owner: string,
+  repo: string,
+  page?: number,
+  perPage?: number,
+  sha?: string
+) {
+  return githubRequest(
+    buildUrl(`https://api.github.com/repos/${owner}/${repo}/commits`, {
+      page: page?.toString(),
+      per_page: perPage?.toString(),
+      sha
+    })
+  );
+}
\ No newline at end of file
diff --git a/src/github/operations/files.ts b/src/github/operations/files.ts
new file mode 100644
index 00000000..9517946e
--- /dev/null
+++ b/src/github/operations/files.ts
@@ -0,0 +1,219 @@
+import { z } from "zod";
+import { githubRequest } from "../common/utils.js";
+import {
+  GitHubContentSchema,
+  GitHubAuthorSchema,
+  GitHubTreeSchema,
+  GitHubCommitSchema,
+  GitHubReferenceSchema,
+  GitHubFileContentSchema,
+} from "../common/types.js";
+
+// Schema definitions
+export const FileOperationSchema = z.object({
+  path: z.string(),
+  content: z.string(),
+});
+
+export const CreateOrUpdateFileSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  path: z.string().describe("Path where to create/update the file"),
+  content: z.string().describe("Content of the file"),
+  message: z.string().describe("Commit message"),
+  branch: z.string().describe("Branch to create/update the file in"),
+  sha: z.string().optional().describe("SHA of the file being replaced (required when updating existing files)"),
+});
+
+export const GetFileContentsSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  path: z.string().describe("Path to the file or directory"),
+  branch: z.string().optional().describe("Branch to get contents from"),
+});
+
+export const PushFilesSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  branch: z.string().describe("Branch to push to (e.g., 'main' or 'master')"),
+  files: z.array(FileOperationSchema).describe("Array of files to push"),
+  message: z.string().describe("Commit message"),
+});
+
+export const GitHubCreateUpdateFileResponseSchema = z.object({
+  content: GitHubFileContentSchema.nullable(),
+  commit: z.object({
+    sha: z.string(),
+    node_id: z.string(),
+    url: z.string(),
+    html_url: z.string(),
+    author: GitHubAuthorSchema,
+    committer: GitHubAuthorSchema,
+    message: z.string(),
+    tree: z.object({
+      sha: z.string(),
+      url: z.string(),
+    }),
+    parents: z.array(
+      z.object({
+        sha: z.string(),
+        url: z.string(),
+        html_url: z.string(),
+      })
+    ),
+  }),
+});
+
+// Type exports
+export type FileOperation = z.infer<typeof FileOperationSchema>;
+export type GitHubCreateUpdateFileResponse = z.infer<typeof GitHubCreateUpdateFileResponseSchema>;
+
+// Function implementations
+export async function getFileContents(
+  owner: string,
+  repo: string,
+  path: string,
+  branch?: string
+) {
+  let url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
+  if (branch) {
+    url += `?ref=${branch}`;
+  }
+
+  const response = await githubRequest(url);
+  const data = GitHubContentSchema.parse(response);
+
+  // If it's a file, decode the content
+  if (!Array.isArray(data) && data.content) {
+    data.content = Buffer.from(data.content, "base64").toString("utf8");
+  }
+
+  return data;
+}
+
+export async function createOrUpdateFile(
+  owner: string,
+  repo: string,
+  path: string,
+  content: string,
+  message: string,
+  branch: string,
+  sha?: string
+) {
+  const encodedContent = Buffer.from(content).toString("base64");
+
+  let currentSha = sha;
+  if (!currentSha) {
+    try {
+      const existingFile = await getFileContents(owner, repo, path, branch);
+      if (!Array.isArray(existingFile)) {
+        currentSha = existingFile.sha;
+      }
+    } catch (error) {
+      console.error("Note: File does not exist in branch, will create new file");
+    }
+  }
+
+  const url = `https://api.github.com/repos/${owner}/${repo}/contents/${path}`;
+  const body = {
+    message,
+    content: encodedContent,
+    branch,
+    ...(currentSha ? { sha: currentSha } : {}),
+  };
+
+  const response = await githubRequest(url, {
+    method: "PUT",
+    body,
+  });
+
+  return GitHubCreateUpdateFileResponseSchema.parse(response);
+}
+
+async function createTree(
+  owner: string,
+  repo: string,
+  files: FileOperation[],
+  baseTree?: string
+) {
+  const tree = files.map((file) => ({
+    path: file.path,
+    mode: "100644" as const,
+    type: "blob" as const,
+    content: file.content,
+  }));
+
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/trees`,
+    {
+      method: "POST",
+      body: {
+        tree,
+        base_tree: baseTree,
+      },
+    }
+  );
+
+  return GitHubTreeSchema.parse(response);
+}
+
+async function createCommit(
+  owner: string,
+  repo: string,
+  message: string,
+  tree: string,
+  parents: string[]
+) {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/commits`,
+    {
+      method: "POST",
+      body: {
+        message,
+        tree,
+        parents,
+      },
+    }
+  );
+
+  return GitHubCommitSchema.parse(response);
+}
+
+async function updateReference(
+  owner: string,
+  repo: string,
+  ref: string,
+  sha: string
+) {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/refs/${ref}`,
+    {
+      method: "PATCH",
+      body: {
+        sha,
+        force: true,
+      },
+    }
+  );
+
+  return GitHubReferenceSchema.parse(response);
+}
+
+export async function pushFiles(
+  owner: string,
+  repo: string,
+  branch: string,
+  files: FileOperation[],
+  message: string
+) {
+  const refResponse = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/git/refs/heads/${branch}`
+  );
+
+  const ref = GitHubReferenceSchema.parse(refResponse);
+  const commitSha = ref.object.sha;
+
+  const tree = await createTree(owner, repo, files, commitSha);
+  const commit = await createCommit(owner, repo, message, tree.sha, [commitSha]);
+  return await updateReference(owner, repo, `heads/${branch}`, commit.sha);
+}
diff --git a/src/github/operations/issues.ts b/src/github/operations/issues.ts
new file mode 100644
index 00000000..d2907bf7
--- /dev/null
+++ b/src/github/operations/issues.ts
@@ -0,0 +1,118 @@
+import { z } from "zod";
+import { githubRequest, buildUrl } from "../common/utils.js";
+
+export const GetIssueSchema = z.object({
+  owner: z.string(),
+  repo: z.string(),
+  issue_number: z.number(),
+});
+
+export const IssueCommentSchema = z.object({
+  owner: z.string(),
+  repo: z.string(),
+  issue_number: z.number(),
+  body: z.string(),
+});
+
+export const CreateIssueOptionsSchema = z.object({
+  title: z.string(),
+  body: z.string().optional(),
+  assignees: z.array(z.string()).optional(),
+  milestone: z.number().optional(),
+  labels: z.array(z.string()).optional(),
+});
+
+export const CreateIssueSchema = z.object({
+  owner: z.string(),
+  repo: z.string(),
+  ...CreateIssueOptionsSchema.shape,
+});
+
+export const ListIssuesOptionsSchema = z.object({
+  owner: z.string(),
+  repo: z.string(),
+  direction: z.enum(["asc", "desc"]).optional(),
+  labels: z.array(z.string()).optional(),
+  page: z.number().optional(),
+  per_page: z.number().optional(),
+  since: z.string().optional(),
+  sort: z.enum(["created", "updated", "comments"]).optional(),
+  state: z.enum(["open", "closed", "all"]).optional(),
+});
+
+export const UpdateIssueOptionsSchema = z.object({
+  owner: z.string(),
+  repo: z.string(),
+  issue_number: z.number(),
+  title: z.string().optional(),
+  body: z.string().optional(),
+  assignees: z.array(z.string()).optional(),
+  milestone: z.number().optional(),
+  labels: z.array(z.string()).optional(),
+  state: z.enum(["open", "closed"]).optional(),
+});
+
+export async function getIssue(owner: string, repo: string, issue_number: number) {
+  return githubRequest(`https://api.github.com/repos/${owner}/${repo}/issues/${issue_number}`);
+}
+
+export async function addIssueComment(
+  owner: string,
+  repo: string,
+  issue_number: number,
+  body: string
+) {
+  return githubRequest(`https://api.github.com/repos/${owner}/${repo}/issues/${issue_number}/comments`, {
+    method: "POST",
+    body: { body },
+  });
+}
+
+export async function createIssue(
+  owner: string,
+  repo: string,
+  options: z.infer<typeof CreateIssueOptionsSchema>
+) {
+  return githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/issues`,
+    {
+      method: "POST",
+      body: options,
+    }
+  );
+}
+
+export async function listIssues(
+  owner: string,
+  repo: string,
+  options: Omit<z.infer<typeof ListIssuesOptionsSchema>, "owner" | "repo">
+) {
+  const urlParams: Record<string, string | undefined> = {
+    direction: options.direction,
+    labels: options.labels?.join(","),
+    page: options.page?.toString(),
+    per_page: options.per_page?.toString(),
+    since: options.since,
+    sort: options.sort,
+    state: options.state
+  };
+
+  return githubRequest(
+    buildUrl(`https://api.github.com/repos/${owner}/${repo}/issues`, urlParams)
+  );
+}
+
+export async function updateIssue(
+  owner: string,
+  repo: string,
+  issue_number: number,
+  options: Omit<z.infer<typeof UpdateIssueOptionsSchema>, "owner" | "repo" | "issue_number">
+) {
+  return githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/issues/${issue_number}`,
+    {
+      method: "PATCH",
+      body: options,
+    }
+  );
+}
\ No newline at end of file
diff --git a/src/github/operations/pulls.ts b/src/github/operations/pulls.ts
new file mode 100644
index 00000000..9b1a5bd7
--- /dev/null
+++ b/src/github/operations/pulls.ts
@@ -0,0 +1,302 @@
+import { z } from "zod";
+import { githubRequest } from "../common/utils.js";
+import {
+  GitHubPullRequestSchema,
+  GitHubIssueAssigneeSchema,
+  GitHubRepositorySchema,
+} from "../common/types.js";
+
+// Schema definitions
+export const PullRequestFileSchema = z.object({
+  sha: z.string(),
+  filename: z.string(),
+  status: z.enum(['added', 'removed', 'modified', 'renamed', 'copied', 'changed', 'unchanged']),
+  additions: z.number(),
+  deletions: z.number(),
+  changes: z.number(),
+  blob_url: z.string(),
+  raw_url: z.string(),
+  contents_url: z.string(),
+  patch: z.string().optional()
+});
+
+export const StatusCheckSchema = z.object({
+  url: z.string(),
+  state: z.enum(['error', 'failure', 'pending', 'success']),
+  description: z.string().nullable(),
+  target_url: z.string().nullable(),
+  context: z.string(),
+  created_at: z.string(),
+  updated_at: z.string()
+});
+
+export const CombinedStatusSchema = z.object({
+  state: z.enum(['error', 'failure', 'pending', 'success']),
+  statuses: z.array(StatusCheckSchema),
+  sha: z.string(),
+  total_count: z.number()
+});
+
+export const PullRequestCommentSchema = z.object({
+  url: z.string(),
+  id: z.number(),
+  node_id: z.string(),
+  pull_request_review_id: z.number().nullable(),
+  diff_hunk: z.string(),
+  path: z.string().nullable(),
+  position: z.number().nullable(),
+  original_position: z.number().nullable(),
+  commit_id: z.string(),
+  original_commit_id: z.string(),
+  user: GitHubIssueAssigneeSchema,
+  body: z.string(),
+  created_at: z.string(),
+  updated_at: z.string(),
+  html_url: z.string(),
+  pull_request_url: z.string(),
+  author_association: z.string(),
+  _links: z.object({
+    self: z.object({ href: z.string() }),
+    html: z.object({ href: z.string() }),
+    pull_request: z.object({ href: z.string() })
+  })
+});
+
+export const PullRequestReviewSchema = z.object({
+  id: z.number(),
+  node_id: z.string(),
+  user: GitHubIssueAssigneeSchema,
+  body: z.string().nullable(),
+  state: z.enum(['APPROVED', 'CHANGES_REQUESTED', 'COMMENTED', 'DISMISSED', 'PENDING']),
+  html_url: z.string(),
+  pull_request_url: z.string(),
+  commit_id: z.string(),
+  submitted_at: z.string().nullable(),
+  author_association: z.string()
+});
+
+// Input schemas
+export const CreatePullRequestSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  title: z.string().describe("Pull request title"),
+  body: z.string().optional().describe("Pull request body/description"),
+  head: z.string().describe("The name of the branch where your changes are implemented"),
+  base: z.string().describe("The name of the branch you want the changes pulled into"),
+  draft: z.boolean().optional().describe("Whether to create the pull request as a draft"),
+  maintainer_can_modify: z.boolean().optional().describe("Whether maintainers can modify the pull request")
+});
+
+export const GetPullRequestSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number")
+});
+
+export const ListPullRequestsSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  state: z.enum(['open', 'closed', 'all']).optional().describe("State of the pull requests to return"),
+  head: z.string().optional().describe("Filter by head user or head organization and branch name"),
+  base: z.string().optional().describe("Filter by base branch name"),
+  sort: z.enum(['created', 'updated', 'popularity', 'long-running']).optional().describe("What to sort results by"),
+  direction: z.enum(['asc', 'desc']).optional().describe("The direction of the sort"),
+  per_page: z.number().optional().describe("Results per page (max 100)"),
+  page: z.number().optional().describe("Page number of the results")
+});
+
+export const CreatePullRequestReviewSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number"),
+  commit_id: z.string().optional().describe("The SHA of the commit that needs a review"),
+  body: z.string().describe("The body text of the review"),
+  event: z.enum(['APPROVE', 'REQUEST_CHANGES', 'COMMENT']).describe("The review action to perform"),
+  comments: z.array(z.object({
+    path: z.string().describe("The relative path to the file being commented on"),
+    position: z.number().describe("The position in the diff where you want to add a review comment"),
+    body: z.string().describe("Text of the review comment")
+  })).optional().describe("Comments to post as part of the review")
+});
+
+export const MergePullRequestSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number"),
+  commit_title: z.string().optional().describe("Title for the automatic commit message"),
+  commit_message: z.string().optional().describe("Extra detail to append to automatic commit message"),
+  merge_method: z.enum(['merge', 'squash', 'rebase']).optional().describe("Merge method to use")
+});
+
+export const GetPullRequestFilesSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"), 
+  pull_number: z.number().describe("Pull request number")
+});
+
+export const GetPullRequestStatusSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number")
+});
+
+export const UpdatePullRequestBranchSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number"),
+  expected_head_sha: z.string().optional().describe("The expected SHA of the pull request's HEAD ref")
+});
+
+export const GetPullRequestCommentsSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number")
+});
+
+export const GetPullRequestReviewsSchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  pull_number: z.number().describe("Pull request number")
+});
+
+// Function implementations
+export async function createPullRequest(
+  params: z.infer<typeof CreatePullRequestSchema>
+): Promise<z.infer<typeof GitHubPullRequestSchema>> {
+  const { owner, repo, ...options } = CreatePullRequestSchema.parse(params);
+
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls`,
+    {
+      method: "POST",
+      body: options,
+    }
+  );
+
+  return GitHubPullRequestSchema.parse(response);
+}
+
+export async function getPullRequest(
+  owner: string,
+  repo: string,
+  pullNumber: number
+): Promise<z.infer<typeof GitHubPullRequestSchema>> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}`
+  );
+  return GitHubPullRequestSchema.parse(response);
+}
+
+export async function listPullRequests(
+  owner: string,
+  repo: string,
+  options: Omit<z.infer<typeof ListPullRequestsSchema>, 'owner' | 'repo'>
+): Promise<z.infer<typeof GitHubPullRequestSchema>[]> {
+  const url = new URL(`https://api.github.com/repos/${owner}/${repo}/pulls`);
+  
+  if (options.state) url.searchParams.append('state', options.state);
+  if (options.head) url.searchParams.append('head', options.head);
+  if (options.base) url.searchParams.append('base', options.base);
+  if (options.sort) url.searchParams.append('sort', options.sort);
+  if (options.direction) url.searchParams.append('direction', options.direction);
+  if (options.per_page) url.searchParams.append('per_page', options.per_page.toString());
+  if (options.page) url.searchParams.append('page', options.page.toString());
+
+  const response = await githubRequest(url.toString());
+  return z.array(GitHubPullRequestSchema).parse(response);
+}
+
+export async function createPullRequestReview(
+  owner: string,
+  repo: string,
+  pullNumber: number,
+  options: Omit<z.infer<typeof CreatePullRequestReviewSchema>, 'owner' | 'repo' | 'pull_number'>
+): Promise<z.infer<typeof PullRequestReviewSchema>> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/reviews`,
+    {
+      method: 'POST',
+      body: options,
+    }
+  );
+  return PullRequestReviewSchema.parse(response);
+}
+
+export async function mergePullRequest(
+  owner: string,
+  repo: string,
+  pullNumber: number,
+  options: Omit<z.infer<typeof MergePullRequestSchema>, 'owner' | 'repo' | 'pull_number'>
+): Promise<any> {
+  return githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/merge`,
+    {
+      method: 'PUT',
+      body: options,
+    }
+  );
+}
+
+export async function getPullRequestFiles(
+  owner: string,
+  repo: string,
+  pullNumber: number
+): Promise<z.infer<typeof PullRequestFileSchema>[]> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/files`
+  );
+  return z.array(PullRequestFileSchema).parse(response);
+}
+
+export async function updatePullRequestBranch(
+  owner: string,
+  repo: string,
+  pullNumber: number,
+  expectedHeadSha?: string
+): Promise<void> {
+  await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/update-branch`,
+    {
+      method: "PUT",
+      body: expectedHeadSha ? { expected_head_sha: expectedHeadSha } : undefined,
+    }
+  );
+}
+
+export async function getPullRequestComments(
+  owner: string,
+  repo: string,
+  pullNumber: number
+): Promise<z.infer<typeof PullRequestCommentSchema>[]> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/comments`
+  );
+  return z.array(PullRequestCommentSchema).parse(response);
+}
+
+export async function getPullRequestReviews(
+  owner: string,
+  repo: string,
+  pullNumber: number
+): Promise<z.infer<typeof PullRequestReviewSchema>[]> {
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/pulls/${pullNumber}/reviews`
+  );
+  return z.array(PullRequestReviewSchema).parse(response);
+}
+
+export async function getPullRequestStatus(
+  owner: string,
+  repo: string,
+  pullNumber: number
+): Promise<z.infer<typeof CombinedStatusSchema>> {
+  // First get the PR to get the head SHA
+  const pr = await getPullRequest(owner, repo, pullNumber);
+  const sha = pr.head.sha;
+
+  // Then get the combined status for that SHA
+  const response = await githubRequest(
+    `https://api.github.com/repos/${owner}/${repo}/commits/${sha}/status`
+  );
+  return CombinedStatusSchema.parse(response);
+}
\ No newline at end of file
diff --git a/src/github/operations/repository.ts b/src/github/operations/repository.ts
new file mode 100644
index 00000000..4cf0ab9b
--- /dev/null
+++ b/src/github/operations/repository.ts
@@ -0,0 +1,65 @@
+import { z } from "zod";
+import { githubRequest } from "../common/utils.js";
+import { GitHubRepositorySchema, GitHubSearchResponseSchema } from "../common/types.js";
+
+// Schema definitions
+export const CreateRepositoryOptionsSchema = z.object({
+  name: z.string().describe("Repository name"),
+  description: z.string().optional().describe("Repository description"),
+  private: z.boolean().optional().describe("Whether the repository should be private"),
+  autoInit: z.boolean().optional().describe("Initialize with README.md"),
+});
+
+export const SearchRepositoriesSchema = z.object({
+  query: z.string().describe("Search query (see GitHub search syntax)"),
+  page: z.number().optional().describe("Page number for pagination (default: 1)"),
+  perPage: z.number().optional().describe("Number of results per page (default: 30, max: 100)"),
+});
+
+export const ForkRepositorySchema = z.object({
+  owner: z.string().describe("Repository owner (username or organization)"),
+  repo: z.string().describe("Repository name"),
+  organization: z.string().optional().describe("Optional: organization to fork to (defaults to your personal account)"),
+});
+
+// Type exports
+export type CreateRepositoryOptions = z.infer<typeof CreateRepositoryOptionsSchema>;
+
+// Function implementations
+export async function createRepository(options: CreateRepositoryOptions) {
+  const response = await githubRequest("https://api.github.com/user/repos", {
+    method: "POST",
+    body: options,
+  });
+  return GitHubRepositorySchema.parse(response);
+}
+
+export async function searchRepositories(
+  query: string,
+  page: number = 1,
+  perPage: number = 30
+) {
+  const url = new URL("https://api.github.com/search/repositories");
+  url.searchParams.append("q", query);
+  url.searchParams.append("page", page.toString());
+  url.searchParams.append("per_page", perPage.toString());
+
+  const response = await githubRequest(url.toString());
+  return GitHubSearchResponseSchema.parse(response);
+}
+
+export async function forkRepository(
+  owner: string,
+  repo: string,
+  organization?: string
+) {
+  const url = organization
+    ? `https://api.github.com/repos/${owner}/${repo}/forks?organization=${organization}`
+    : `https://api.github.com/repos/${owner}/${repo}/forks`;
+
+  const response = await githubRequest(url, { method: "POST" });
+  return GitHubRepositorySchema.extend({
+    parent: GitHubRepositorySchema,
+    source: GitHubRepositorySchema,
+  }).parse(response);
+}
diff --git a/src/github/operations/search.ts b/src/github/operations/search.ts
new file mode 100644
index 00000000..76faa729
--- /dev/null
+++ b/src/github/operations/search.ts
@@ -0,0 +1,45 @@
+import { z } from "zod";
+import { githubRequest, buildUrl } from "../common/utils.js";
+
+export const SearchOptions = z.object({
+  q: z.string(),
+  order: z.enum(["asc", "desc"]).optional(),
+  page: z.number().min(1).optional(),
+  per_page: z.number().min(1).max(100).optional(),
+});
+
+export const SearchUsersOptions = SearchOptions.extend({
+  sort: z.enum(["followers", "repositories", "joined"]).optional(),
+});
+
+export const SearchIssuesOptions = SearchOptions.extend({
+  sort: z.enum([
+    "comments",
+    "reactions",
+    "reactions-+1",
+    "reactions--1",
+    "reactions-smile",
+    "reactions-thinking_face",
+    "reactions-heart",
+    "reactions-tada",
+    "interactions",
+    "created",
+    "updated",
+  ]).optional(),
+});
+
+export const SearchCodeSchema = SearchOptions;
+export const SearchUsersSchema = SearchUsersOptions;
+export const SearchIssuesSchema = SearchIssuesOptions;
+
+export async function searchCode(params: z.infer<typeof SearchCodeSchema>) {
+  return githubRequest(buildUrl("https://api.github.com/search/code", params));
+}
+
+export async function searchIssues(params: z.infer<typeof SearchIssuesSchema>) {
+  return githubRequest(buildUrl("https://api.github.com/search/issues", params));
+}
+
+export async function searchUsers(params: z.infer<typeof SearchUsersSchema>) {
+  return githubRequest(buildUrl("https://api.github.com/search/users", params));
+}
\ No newline at end of file
diff --git a/src/github/schemas.ts b/src/github/schemas.ts
deleted file mode 100644
index 0a322328..00000000
--- a/src/github/schemas.ts
+++ /dev/null
@@ -1,719 +0,0 @@
-import { z } from "zod";
-
-// Base schemas for common types
-export const GitHubAuthorSchema = z.object({
-  name: z.string(),
-  email: z.string(),
-  date: z.string(),
-});
-
-// Repository related schemas
-export const GitHubOwnerSchema = z.object({
-  login: z.string(),
-  id: z.number(),
-  node_id: z.string(),
-  avatar_url: z.string(),
-  url: z.string(),
-  html_url: z.string(),
-  type: z.string(),
-});
-
-export const GitHubRepositorySchema = z.object({
-  id: z.number(),
-  node_id: z.string(),
-  name: z.string(),
-  full_name: z.string(),
-  private: z.boolean(),
-  owner: GitHubOwnerSchema,
-  html_url: z.string(),
-  description: z.string().nullable(),
-  fork: z.boolean(),
-  url: z.string(),
-  created_at: z.string(),
-  updated_at: z.string(),
-  pushed_at: z.string(),
-  git_url: z.string(),
-  ssh_url: z.string(),
-  clone_url: z.string(),
-  default_branch: z.string(),
-});
-
-// File content schemas
-export const GitHubFileContentSchema = z.object({
-  type: z.string(),
-  encoding: z.string(),
-  size: z.number(),
-  name: z.string(),
-  path: z.string(),
-  content: z.string(),
-  sha: z.string(),
-  url: z.string(),
-  git_url: z.string(),
-  html_url: z.string(),
-  download_url: z.string(),
-});
-
-export const GitHubDirectoryContentSchema = z.object({
-  type: z.string(),
-  size: z.number(),
-  name: z.string(),
-  path: z.string(),
-  sha: z.string(),
-  url: z.string(),
-  git_url: z.string(),
-  html_url: z.string(),
-  download_url: z.string().nullable(),
-});
-
-export const GitHubContentSchema = z.union([
-  GitHubFileContentSchema,
-  z.array(GitHubDirectoryContentSchema),
-]);
-
-// Operation schemas
-export const FileOperationSchema = z.object({
-  path: z.string(),
-  content: z.string(),
-});
-
-// Tree and commit schemas
-export const GitHubTreeEntrySchema = z.object({
-  path: z.string(),
-  mode: z.enum(["100644", "100755", "040000", "160000", "120000"]),
-  type: z.enum(["blob", "tree", "commit"]),
-  size: z.number().optional(),
-  sha: z.string(),
-  url: z.string(),
-});
-
-export const GitHubTreeSchema = z.object({
-  sha: z.string(),
-  url: z.string(),
-  tree: z.array(GitHubTreeEntrySchema),
-  truncated: z.boolean(),
-});
-
-export const GitHubListCommitsSchema = z.array(z.object({
-  sha: z.string(),
-  node_id: z.string(),
-  commit: z.object({
-    author: GitHubAuthorSchema,
-    committer: GitHubAuthorSchema,
-    message: z.string(),
-    tree: z.object({
-      sha: z.string(),
-      url: z.string()
-    }),
-    url: z.string(),
-    comment_count: z.number(),
-  }),
-  url: z.string(),
-  html_url: z.string(),
-  comments_url: z.string()
-}));
-
-export const GitHubCommitSchema = z.object({
-  sha: z.string(),
-  node_id: z.string(),
-  url: z.string(),
-  author: GitHubAuthorSchema,
-  committer: GitHubAuthorSchema,
-  message: z.string(),
-  tree: z.object({
-    sha: z.string(),
-    url: z.string(),
-  }),
-  parents: z.array(
-    z.object({
-      sha: z.string(),
-      url: z.string(),
-    })
-  ),
-});
-
-// Reference schema
-export const GitHubReferenceSchema = z.object({
-  ref: z.string(),
-  node_id: z.string(),
-  url: z.string(),
-  object: z.object({
-    sha: z.string(),
-    type: z.string(),
-    url: z.string(),
-  }),
-});
-
-// Input schemas for operations
-export const CreateRepositoryOptionsSchema = z.object({
-  name: z.string(),
-  description: z.string().optional(),
-  private: z.boolean().optional(),
-  auto_init: z.boolean().optional(),
-});
-
-export const CreateIssueOptionsSchema = z.object({
-  title: z.string(),
-  body: z.string().optional(),
-  assignees: z.array(z.string()).optional(),
-  milestone: z.number().optional(),
-  labels: z.array(z.string()).optional(),
-});
-
-export const CreatePullRequestOptionsSchema = z.object({
-  title: z.string(),
-  body: z.string().optional(),
-  head: z.string(),
-  base: z.string(),
-  maintainer_can_modify: z.boolean().optional(),
-  draft: z.boolean().optional(),
-});
-
-export const CreateBranchOptionsSchema = z.object({
-  ref: z.string(),
-  sha: z.string(),
-});
-
-// Response schemas for operations
-export const GitHubCreateUpdateFileResponseSchema = z.object({
-  content: GitHubFileContentSchema.nullable(),
-  commit: z.object({
-    sha: z.string(),
-    node_id: z.string(),
-    url: z.string(),
-    html_url: z.string(),
-    author: GitHubAuthorSchema,
-    committer: GitHubAuthorSchema,
-    message: z.string(),
-    tree: z.object({
-      sha: z.string(),
-      url: z.string(),
-    }),
-    parents: z.array(
-      z.object({
-        sha: z.string(),
-        url: z.string(),
-        html_url: z.string(),
-      })
-    ),
-  }),
-});
-
-export const GitHubSearchResponseSchema = z.object({
-  total_count: z.number(),
-  incomplete_results: z.boolean(),
-  items: z.array(GitHubRepositorySchema),
-});
-
-// Fork related schemas
-export const GitHubForkParentSchema = z.object({
-  name: z.string(),
-  full_name: z.string(),
-  owner: z.object({
-    login: z.string(),
-    id: z.number(),
-    avatar_url: z.string(),
-  }),
-  html_url: z.string(),
-});
-
-export const GitHubForkSchema = GitHubRepositorySchema.extend({
-  parent: GitHubForkParentSchema,
-  source: GitHubForkParentSchema,
-});
-
-// Issue related schemas
-export const GitHubLabelSchema = z.object({
-  id: z.number(),
-  node_id: z.string(),
-  url: z.string(),
-  name: z.string(),
-  color: z.string(),
-  default: z.boolean(),
-  description: z.string().optional(),
-});
-
-export const GitHubIssueAssigneeSchema = z.object({
-  login: z.string(),
-  id: z.number(),
-  avatar_url: z.string(),
-  url: z.string(),
-  html_url: z.string(),
-});
-
-export const GitHubMilestoneSchema = z.object({
-  url: z.string(),
-  html_url: z.string(),
-  labels_url: z.string(),
-  id: z.number(),
-  node_id: z.string(),
-  number: z.number(),
-  title: z.string(),
-  description: z.string(),
-  state: z.string(),
-});
-
-export const GitHubIssueSchema = z.object({
-  url: z.string(),
-  repository_url: z.string(),
-  labels_url: z.string(),
-  comments_url: z.string(),
-  events_url: z.string(),
-  html_url: z.string(),
-  id: z.number(),
-  node_id: z.string(),
-  number: z.number(),
-  title: z.string(),
-  user: GitHubIssueAssigneeSchema,
-  labels: z.array(GitHubLabelSchema),
-  state: z.string(),
-  locked: z.boolean(),
-  assignee: GitHubIssueAssigneeSchema.nullable(),
-  assignees: z.array(GitHubIssueAssigneeSchema),
-  milestone: GitHubMilestoneSchema.nullable(),
-  comments: z.number(),
-  created_at: z.string(),
-  updated_at: z.string(),
-  closed_at: z.string().nullable(),
-  body: z.string().nullable(),
-});
-
-// Pull Request related schemas
-export const GitHubPullRequestHeadSchema = z.object({
-  label: z.string(),
-  ref: z.string(),
-  sha: z.string(),
-  user: GitHubIssueAssigneeSchema,
-  repo: GitHubRepositorySchema,
-});
-
-export const GitHubPullRequestSchema = z.object({
-  url: z.string(),
-  id: z.number(),
-  node_id: z.string(),
-  html_url: z.string(),
-  diff_url: z.string(),
-  patch_url: z.string(),
-  issue_url: z.string(),
-  number: z.number(),
-  state: z.string(),
-  locked: z.boolean(),
-  title: z.string(),
-  user: GitHubIssueAssigneeSchema,
-  body: z.string(),
-  created_at: z.string(),
-  updated_at: z.string(),
-  closed_at: z.string().nullable(),
-  merged_at: z.string().nullable(),
-  merge_commit_sha: z.string().nullable(),
-  assignee: GitHubIssueAssigneeSchema.nullable(),
-  assignees: z.array(GitHubIssueAssigneeSchema),
-  head: GitHubPullRequestHeadSchema,
-  base: GitHubPullRequestHeadSchema,
-});
-
-const RepoParamsSchema = z.object({
-  owner: z.string().describe("Repository owner (username or organization)"),
-  repo: z.string().describe("Repository name"),
-});
-
-export const CreateOrUpdateFileSchema = RepoParamsSchema.extend({
-  path: z.string().describe("Path where to create/update the file"),
-  content: z.string().describe("Content of the file"),
-  message: z.string().describe("Commit message"),
-  branch: z.string().describe("Branch to create/update the file in"),
-  sha: z
-    .string()
-    .optional()
-    .describe(
-      "SHA of the file being replaced (required when updating existing files)"
-    ),
-});
-
-export const SearchRepositoriesSchema = z.object({
-  query: z.string().describe("Search query (see GitHub search syntax)"),
-  page: z
-    .number()
-    .optional()
-    .describe("Page number for pagination (default: 1)"),
-  perPage: z
-    .number()
-    .optional()
-    .describe("Number of results per page (default: 30, max: 100)"),
-});
-
-export const ListCommitsSchema = z.object({
-  owner: z.string().describe("Repository owner (username or organization)"),
-  repo: z.string().describe("Repository name"),
-  page: z.number().optional().describe("Page number for pagination (default: 1)"),
-  perPage: z.number().optional().describe("Number of results per page (default: 30, max: 100)"),
-  sha: z.string().optional()
-    .describe("SHA of the file being replaced (required when updating existing files)")
-});
-
-export const CreateRepositorySchema = z.object({
-  name: z.string().describe("Repository name"),
-  description: z.string().optional().describe("Repository description"),
-  private: z
-    .boolean()
-    .optional()
-    .describe("Whether the repository should be private"),
-  autoInit: z.boolean().optional().describe("Initialize with README.md"),
-});
-
-export const GetFileContentsSchema = RepoParamsSchema.extend({
-  path: z.string().describe("Path to the file or directory"),
-  branch: z.string().optional().describe("Branch to get contents from"),
-});
-
-export const PushFilesSchema = RepoParamsSchema.extend({
-  branch: z.string().describe("Branch to push to (e.g., 'main' or 'master')"),
-  files: z
-    .array(
-      z.object({
-        path: z.string().describe("Path where to create the file"),
-        content: z.string().describe("Content of the file"),
-      })
-    )
-    .describe("Array of files to push"),
-  message: z.string().describe("Commit message"),
-});
-
-export const CreateIssueSchema = RepoParamsSchema.extend({
-  title: z.string().describe("Issue title"),
-  body: z.string().optional().describe("Issue body/description"),
-  assignees: z
-    .array(z.string())
-    .optional()
-    .describe("Array of usernames to assign"),
-  labels: z.array(z.string()).optional().describe("Array of label names"),
-  milestone: z.number().optional().describe("Milestone number to assign"),
-});
-
-export const CreatePullRequestSchema = RepoParamsSchema.extend({
-  title: z.string().describe("Pull request title"),
-  body: z.string().optional().describe("Pull request body/description"),
-  head: z
-    .string()
-    .describe("The name of the branch where your changes are implemented"),
-  base: z
-    .string()
-    .describe("The name of the branch you want the changes pulled into"),
-  draft: z
-    .boolean()
-    .optional()
-    .describe("Whether to create the pull request as a draft"),
-  maintainer_can_modify: z
-    .boolean()
-    .optional()
-    .describe("Whether maintainers can modify the pull request"),
-});
-
-export const ForkRepositorySchema = RepoParamsSchema.extend({
-  organization: z
-    .string()
-    .optional()
-    .describe(
-      "Optional: organization to fork to (defaults to your personal account)"
-    ),
-});
-
-export const CreateBranchSchema = RepoParamsSchema.extend({
-  branch: z.string().describe("Name for the new branch"),
-  from_branch: z
-    .string()
-    .optional()
-    .describe(
-      "Optional: source branch to create from (defaults to the repository's default branch)"
-    ),
-});
-
-/**
- * Response schema for a code search result item
- * @see https://docs.github.com/en/rest/search/search?apiVersion=2022-11-28#search-code
- */
-export const SearchCodeItemSchema = z.object({
-  name: z.string().describe("The name of the file"),
-  path: z.string().describe("The path to the file in the repository"),
-  sha: z.string().describe("The SHA hash of the file"),
-  url: z.string().describe("The API URL for this file"),
-  git_url: z.string().describe("The Git URL for this file"),
-  html_url: z.string().describe("The HTML URL to view this file on GitHub"),
-  repository: GitHubRepositorySchema.describe(
-    "The repository where this file was found"
-  ),
-  score: z.number().describe("The search result score"),
-});
-
-/**
- * Response schema for code search results
- */
-export const SearchCodeResponseSchema = z.object({
-  total_count: z.number().describe("Total number of matching results"),
-  incomplete_results: z
-    .boolean()
-    .describe("Whether the results are incomplete"),
-  items: z.array(SearchCodeItemSchema).describe("The search results"),
-});
-
-/**
- * Response schema for an issue search result item
- * @see https://docs.github.com/en/rest/search/search?apiVersion=2022-11-28#search-issues-and-pull-requests
- */
-export const SearchIssueItemSchema = z.object({
-  url: z.string().describe("The API URL for this issue"),
-  repository_url: z
-    .string()
-    .describe("The API URL for the repository where this issue was found"),
-  labels_url: z.string().describe("The API URL for the labels of this issue"),
-  comments_url: z.string().describe("The API URL for comments of this issue"),
-  events_url: z.string().describe("The API URL for events of this issue"),
-  html_url: z.string().describe("The HTML URL to view this issue on GitHub"),
-  id: z.number().describe("The ID of this issue"),
-  node_id: z.string().describe("The Node ID of this issue"),
-  number: z.number().describe("The number of this issue"),
-  title: z.string().describe("The title of this issue"),
-  user: GitHubIssueAssigneeSchema.describe("The user who created this issue"),
-  labels: z.array(GitHubLabelSchema).describe("The labels of this issue"),
-  state: z.string().describe("The state of this issue"),
-  locked: z.boolean().describe("Whether this issue is locked"),
-  assignee: GitHubIssueAssigneeSchema.nullable().describe(
-    "The assignee of this issue"
-  ),
-  assignees: z
-    .array(GitHubIssueAssigneeSchema)
-    .describe("The assignees of this issue"),
-  comments: z.number().describe("The number of comments on this issue"),
-  created_at: z.string().describe("The creation time of this issue"),
-  updated_at: z.string().describe("The last update time of this issue"),
-  closed_at: z.string().nullable().describe("The closure time of this issue"),
-  body: z.string().describe("The body of this issue"),
-  score: z.number().describe("The search result score"),
-  pull_request: z
-    .object({
-      url: z.string().describe("The API URL for this pull request"),
-      html_url: z.string().describe("The HTML URL to view this pull request"),
-      diff_url: z.string().describe("The URL to view the diff"),
-      patch_url: z.string().describe("The URL to view the patch"),
-    })
-    .optional()
-    .describe("Pull request details if this is a PR"),
-});
-
-/**
- * Response schema for issue search results
- */
-export const SearchIssuesResponseSchema = z.object({
-  total_count: z.number().describe("Total number of matching results"),
-  incomplete_results: z
-    .boolean()
-    .describe("Whether the results are incomplete"),
-  items: z.array(SearchIssueItemSchema).describe("The search results"),
-});
-
-/**
- * Response schema for a user search result item
- * @see https://docs.github.com/en/rest/search/search?apiVersion=2022-11-28#search-users
- */
-export const SearchUserItemSchema = z.object({
-  login: z.string().describe("The username of the user"),
-  id: z.number().describe("The ID of the user"),
-  node_id: z.string().describe("The Node ID of the user"),
-  avatar_url: z.string().describe("The avatar URL of the user"),
-  gravatar_id: z.string().describe("The Gravatar ID of the user"),
-  url: z.string().describe("The API URL for this user"),
-  html_url: z.string().describe("The HTML URL to view this user on GitHub"),
-  followers_url: z.string().describe("The API URL for followers of this user"),
-  following_url: z.string().describe("The API URL for following of this user"),
-  gists_url: z.string().describe("The API URL for gists of this user"),
-  starred_url: z
-    .string()
-    .describe("The API URL for starred repositories of this user"),
-  subscriptions_url: z
-    .string()
-    .describe("The API URL for subscriptions of this user"),
-  organizations_url: z
-    .string()
-    .describe("The API URL for organizations of this user"),
-  repos_url: z.string().describe("The API URL for repositories of this user"),
-  events_url: z.string().describe("The API URL for events of this user"),
-  received_events_url: z
-    .string()
-    .describe("The API URL for received events of this user"),
-  type: z.string().describe("The type of this user"),
-  site_admin: z.boolean().describe("Whether this user is a site administrator"),
-  score: z.number().describe("The search result score"),
-});
-
-/**
- * Response schema for user search results
- */
-export const SearchUsersResponseSchema = z.object({
-  total_count: z.number().describe("Total number of matching results"),
-  incomplete_results: z
-    .boolean()
-    .describe("Whether the results are incomplete"),
-  items: z.array(SearchUserItemSchema).describe("The search results"),
-});
-
-/**
- * Input schema for code search
- * @see https://docs.github.com/en/rest/search/search?apiVersion=2022-11-28#search-code--parameters
- */
-export const SearchCodeSchema = z.object({
-  q: z
-    .string()
-    .describe(
-      "Search query. See GitHub code search syntax: https://docs.github.com/en/search-github/searching-on-github/searching-code"
-    ),
-  order: z
-    .enum(["asc", "desc"])
-    .optional()
-    .describe("Sort order (asc or desc)"),
-  per_page: z
-    .number()
-    .min(1)
-    .max(100)
-    .optional()
-    .describe("Results per page (max 100)"),
-  page: z.number().min(1).optional().describe("Page number"),
-});
-
-/**
- * Input schema for issues search
- * @see https://docs.github.com/en/rest/search/search?apiVersion=2022-11-28#search-issues-and-pull-requests--parameters
- */
-export const SearchIssuesSchema = z.object({
-  q: z
-    .string()
-    .describe(
-      "Search query. See GitHub issues search syntax: https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests"
-    ),
-  sort: z
-    .enum([
-      "comments",
-      "reactions",
-      "reactions-+1",
-      "reactions--1",
-      "reactions-smile",
-      "reactions-thinking_face",
-      "reactions-heart",
-      "reactions-tada",
-      "interactions",
-      "created",
-      "updated",
-    ])
-    .optional()
-    .describe("Sort field"),
-  order: z
-    .enum(["asc", "desc"])
-    .optional()
-    .describe("Sort order (asc or desc)"),
-  per_page: z
-    .number()
-    .min(1)
-    .max(100)
-    .optional()
-    .describe("Results per page (max 100)"),
-  page: z.number().min(1).optional().describe("Page number"),
-});
-
-/**
- * Input schema for users search
- * @see https://docs.github.com/en/rest/search/search?apiVersion=2022-11-28#search-users--parameters
- */
-export const SearchUsersSchema = z.object({
-  q: z
-    .string()
-    .describe(
-      "Search query. See GitHub users search syntax: https://docs.github.com/en/search-github/searching-on-github/searching-users"
-    ),
-  sort: z
-    .enum(["followers", "repositories", "joined"])
-    .optional()
-    .describe("Sort field"),
-  order: z
-    .enum(["asc", "desc"])
-    .optional()
-    .describe("Sort order (asc or desc)"),
-  per_page: z
-    .number()
-    .min(1)
-    .max(100)
-    .optional()
-    .describe("Results per page (max 100)"),
-  page: z.number().min(1).optional().describe("Page number"),
-});
-
-// Add these schema definitions for issue management
-
-export const ListIssuesOptionsSchema = z.object({
-  owner: z.string(),
-  repo: z.string(),
-  state: z.enum(['open', 'closed', 'all']).optional(),
-  labels: z.array(z.string()).optional(),
-  sort: z.enum(['created', 'updated', 'comments']).optional(),
-  direction: z.enum(['asc', 'desc']).optional(),
-  since: z.string().optional(), // ISO 8601 timestamp
-  page: z.number().optional(),
-  per_page: z.number().optional()
-});
-
-export const UpdateIssueOptionsSchema = z.object({
-  owner: z.string(),
-  repo: z.string(),
-  issue_number: z.number(),
-  title: z.string().optional(),
-  body: z.string().optional(),
-  state: z.enum(['open', 'closed']).optional(),
-  labels: z.array(z.string()).optional(),
-  assignees: z.array(z.string()).optional(),
-  milestone: z.number().optional()
-});
-
-export const IssueCommentSchema = z.object({
-  owner: z.string(),
-  repo: z.string(),
-  issue_number: z.number(),
-  body: z.string()
-});
-
-export const GetIssueSchema = z.object({
-  owner: z.string().describe("Repository owner (username or organization)"),
-  repo: z.string().describe("Repository name"),
-  issue_number: z.number().describe("Issue number")
-});
-
-// Export types
-export type GitHubAuthor = z.infer<typeof GitHubAuthorSchema>;
-export type GitHubFork = z.infer<typeof GitHubForkSchema>;
-export type GitHubIssue = z.infer<typeof GitHubIssueSchema>;
-export type GitHubPullRequest = z.infer<typeof GitHubPullRequestSchema>;
-export type GitHubRepository = z.infer<typeof GitHubRepositorySchema>;
-export type GitHubFileContent = z.infer<typeof GitHubFileContentSchema>;
-export type GitHubDirectoryContent = z.infer<
-  typeof GitHubDirectoryContentSchema
->;
-export type GitHubContent = z.infer<typeof GitHubContentSchema>;
-export type FileOperation = z.infer<typeof FileOperationSchema>;
-export type GitHubTree = z.infer<typeof GitHubTreeSchema>;
-export type GitHubCommit = z.infer<typeof GitHubCommitSchema>;
-export type GitHubListCommits = z.infer<typeof GitHubListCommitsSchema>;
-export type GitHubReference = z.infer<typeof GitHubReferenceSchema>;
-export type CreateRepositoryOptions = z.infer<
-  typeof CreateRepositoryOptionsSchema
->;
-export type CreateIssueOptions = z.infer<typeof CreateIssueOptionsSchema>;
-export type CreatePullRequestOptions = z.infer<
-  typeof CreatePullRequestOptionsSchema
->;
-export type CreateBranchOptions = z.infer<typeof CreateBranchOptionsSchema>;
-export type GitHubCreateUpdateFileResponse = z.infer<
-  typeof GitHubCreateUpdateFileResponseSchema
->;
-export type GitHubSearchResponse = z.infer<typeof GitHubSearchResponseSchema>;
-export type SearchCodeItem = z.infer<typeof SearchCodeItemSchema>;
-export type SearchCodeResponse = z.infer<typeof SearchCodeResponseSchema>;
-export type SearchIssueItem = z.infer<typeof SearchIssueItemSchema>;
-export type SearchIssuesResponse = z.infer<typeof SearchIssuesResponseSchema>;
-export type SearchUserItem = z.infer<typeof SearchUserItemSchema>;
-export type SearchUsersResponse = z.infer<typeof SearchUsersResponseSchema>;