From 2370b8b2438b4e56f9656a44ffe034e2e1676119 Mon Sep 17 00:00:00 2001 From: "codeglide[bot]" <223743026+codeglide[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 22:29:58 +0000 Subject: [PATCH 1/2] feat: Updated MCP server with latest generated code --- MCP/README.md | 208 + MCP/config/config.go | 48 + MCP/go.mod | 17 + MCP/go.sum | 39 + MCP/main.go | 145 + MCP/models/models.go | 10131 ++++++++++++++++ MCP/registry.go | 1085 ++ ...om_labels_to_self_hosted_runner_for_org.go | 105 + ...m_labels_to_self_hosted_runner_for_repo.go | 114 + ...cess_to_self_hosted_runner_group_in_org.go | 95 + ...actions_add_selected_repo_to_org_secret.go | 95 + ...tions_add_selected_repo_to_org_variable.go | 95 + ...add_self_hosted_runner_to_group_for_org.go | 95 + .../actions/actions_approve_workflow_run.go | 95 + .../actions/actions_cancel_workflow_run.go | 95 + .../actions_create_environment_variable.go | 115 + .../actions_create_hosted_runner_for_org.go | 101 + ...ons_create_or_update_environment_secret.go | 124 + .../actions_create_or_update_org_secret.go | 108 + .../actions_create_or_update_repo_secret.go | 115 + .../actions/actions_create_org_variable.go | 99 + ...tions_create_registration_token_for_org.go | 77 + ...ions_create_registration_token_for_repo.go | 86 + .../actions_create_remove_token_for_org.go | 77 + .../actions_create_remove_token_for_repo.go | 86 + .../actions/actions_create_repo_variable.go | 106 + ...create_self_hosted_runner_group_for_org.go | 103 + .../actions_create_workflow_dispatch.go | 115 + .../actions_delete_actions_cache_by_id.go | 95 + .../actions_delete_actions_cache_by_key.go | 100 + MCP/tools/actions/actions_delete_artifact.go | 95 + .../actions_delete_environment_secret.go | 104 + .../actions_delete_environment_variable.go | 104 + .../actions_delete_hosted_runner_for_org.go | 86 + .../actions/actions_delete_org_secret.go | 86 + .../actions/actions_delete_org_variable.go | 86 + .../actions/actions_delete_repo_secret.go | 95 + .../actions/actions_delete_repo_variable.go | 95 + ...ions_delete_self_hosted_runner_from_org.go | 86 + ...ons_delete_self_hosted_runner_from_repo.go | 95 + ...elete_self_hosted_runner_group_from_org.go | 86 + .../actions/actions_delete_workflow_run.go | 95 + .../actions_delete_workflow_run_logs.go | 95 + ..._repository_github_actions_organization.go | 86 + MCP/tools/actions/actions_disable_workflow.go | 95 + .../actions/actions_download_artifact.go | 104 + ...ions_download_job_logs_for_workflow_run.go | 95 + ...ions_download_workflow_run_attempt_logs.go | 104 + .../actions_download_workflow_run_logs.go | 95 + ..._repository_github_actions_organization.go | 86 + MCP/tools/actions/actions_enable_workflow.go | 95 + .../actions_force_cancel_workflow_run.go | 95 + ...tions_generate_runner_jitconfig_for_org.go | 99 + ...ions_generate_runner_jitconfig_for_repo.go | 108 + .../actions/actions_get_actions_cache_list.go | 116 + .../actions_get_actions_cache_usage.go | 86 + ...get_actions_cache_usage_by_repo_for_org.go | 91 + ...actions_get_actions_cache_usage_for_org.go | 77 + ...ctions_get_allowed_actions_organization.go | 77 + .../actions_get_allowed_actions_repository.go | 86 + MCP/tools/actions/actions_get_artifact.go | 95 + ...ions_get_custom_oidc_sub_claim_for_repo.go | 86 + .../actions_get_environment_public_key.go | 95 + .../actions/actions_get_environment_secret.go | 104 + .../actions_get_environment_variable.go | 104 + ...fault_workflow_permissions_organization.go | 77 + ...default_workflow_permissions_repository.go | 86 + ...github_actions_permissions_organization.go | 77 + ...t_github_actions_permissions_repository.go | 86 + .../actions_get_hosted_runner_for_org.go | 86 + ...ted_runners_github_owned_images_for_org.go | 77 + ...tions_get_hosted_runners_limits_for_org.go | 77 + ...et_hosted_runners_machine_specs_for_org.go | 77 + ...t_hosted_runners_partner_images_for_org.go | 77 + ...ns_get_hosted_runners_platforms_for_org.go | 77 + .../actions_get_job_for_workflow_run.go | 95 + .../actions/actions_get_org_public_key.go | 77 + MCP/tools/actions/actions_get_org_secret.go | 86 + MCP/tools/actions/actions_get_org_variable.go | 86 + ...actions_get_pending_deployments_for_run.go | 95 + .../actions/actions_get_repo_public_key.go | 86 + MCP/tools/actions/actions_get_repo_secret.go | 95 + .../actions/actions_get_repo_variable.go | 95 + .../actions/actions_get_reviews_for_run.go | 95 + .../actions_get_self_hosted_runner_for_org.go | 86 + ...actions_get_self_hosted_runner_for_repo.go | 95 + ...ns_get_self_hosted_runner_group_for_org.go | 86 + MCP/tools/actions/actions_get_workflow.go | 95 + ...tions_get_workflow_access_to_repository.go | 86 + MCP/tools/actions/actions_get_workflow_run.go | 105 + .../actions_get_workflow_run_attempt.go | 114 + .../actions/actions_get_workflow_run_usage.go | 95 + .../actions/actions_get_workflow_usage.go | 95 + .../actions_list_artifacts_for_repo.go | 104 + .../actions_list_environment_secrets.go | 109 + .../actions_list_environment_variables.go | 109 + ..._github_hosted_runners_in_group_for_org.go | 100 + .../actions_list_hosted_runners_for_org.go | 91 + .../actions_list_jobs_for_workflow_run.go | 113 + ...ions_list_jobs_for_workflow_run_attempt.go | 118 + ...t_labels_for_self_hosted_runner_for_org.go | 86 + ..._labels_for_self_hosted_runner_for_repo.go | 95 + MCP/tools/actions/actions_list_org_secrets.go | 91 + .../actions/actions_list_org_variables.go | 91 + ...cess_to_self_hosted_runner_group_in_org.go | 100 + .../actions_list_repo_organization_secrets.go | 100 + ...ctions_list_repo_organization_variables.go | 100 + .../actions/actions_list_repo_secrets.go | 100 + .../actions/actions_list_repo_variables.go | 100 + .../actions/actions_list_repo_workflows.go | 100 + ...ctions_list_runner_applications_for_org.go | 77 + ...tions_list_runner_applications_for_repo.go | 86 + ...ions_list_selected_repos_for_org_secret.go | 100 + ...ns_list_selected_repos_for_org_variable.go | 100 + ...ies_enabled_github_actions_organization.go | 91 + ..._list_self_hosted_runner_groups_for_org.go | 95 + ...ctions_list_self_hosted_runners_for_org.go | 95 + ...tions_list_self_hosted_runners_for_repo.go | 104 + ...st_self_hosted_runners_in_group_for_org.go | 100 + .../actions_list_workflow_run_artifacts.go | 113 + .../actions/actions_list_workflow_runs.go | 141 + .../actions_list_workflow_runs_for_repo.go | 132 + .../actions_re_run_job_for_workflow_run.go | 114 + MCP/tools/actions/actions_re_run_workflow.go | 114 + .../actions_re_run_workflow_failed_jobs.go | 114 + ..._labels_from_self_hosted_runner_for_org.go | 86 + ...labels_from_self_hosted_runner_for_repo.go | 95 + ...m_label_from_self_hosted_runner_for_org.go | 95 + ..._label_from_self_hosted_runner_for_repo.go | 104 + ...cess_to_self_hosted_runner_group_in_org.go | 95 + ...ns_remove_selected_repo_from_org_secret.go | 95 + ..._remove_selected_repo_from_org_variable.go | 95 + ...e_self_hosted_runner_from_group_for_org.go | 95 + .../actions_review_custom_gates_for_run.go | 113 + ...ions_review_pending_deployments_for_run.go | 116 + ...ctions_set_allowed_actions_organization.go | 98 + .../actions_set_allowed_actions_repository.go | 107 + ...m_labels_for_self_hosted_runner_for_org.go | 105 + ..._labels_for_self_hosted_runner_for_repo.go | 114 + ...ions_set_custom_oidc_sub_claim_for_repo.go | 106 + ...fault_workflow_permissions_organization.go | 97 + ...default_workflow_permissions_repository.go | 106 + ...github_actions_permissions_organization.go | 97 + ...t_github_actions_permissions_repository.go | 106 + ...cess_to_self_hosted_runner_group_in_org.go | 105 + ...tions_set_selected_repos_for_org_secret.go | 105 + ...ons_set_selected_repos_for_org_variable.go | 105 + ...ies_enabled_github_actions_organization.go | 96 + ...et_self_hosted_runners_in_group_for_org.go | 105 + ...tions_set_workflow_access_to_repository.go | 105 + .../actions_update_environment_variable.go | 124 + .../actions_update_hosted_runner_for_org.go | 108 + .../actions/actions_update_org_variable.go | 108 + .../actions/actions_update_repo_variable.go | 115 + ...update_self_hosted_runner_group_for_org.go | 110 + ...k_repo_is_starred_by_authenticated_user.go | 86 + .../activity_delete_repo_subscription.go | 86 + .../activity_delete_thread_subscription.go | 77 + MCP/tools/activity/activity_get_feeds.go | 64 + .../activity_get_repo_subscription.go | 86 + MCP/tools/activity/activity_get_thread.go | 77 + ...ead_subscription_for_authenticated_user.go | 77 + ...vity_list_events_for_authenticated_user.go | 91 + ...st_notifications_for_authenticated_user.go | 98 + ..._list_org_events_for_authenticated_user.go | 100 + .../activity/activity_list_public_events.go | 82 + ...ity_list_public_events_for_repo_network.go | 100 + .../activity_list_public_events_for_user.go | 91 + .../activity_list_public_org_events.go | 91 + .../activity_list_received_events_for_user.go | 91 + ...ty_list_received_public_events_for_user.go | 91 + .../activity/activity_list_repo_events.go | 100 + ...po_notifications_for_authenticated_user.go | 116 + ...ist_repos_starred_by_authenticated_user.go | 90 + .../activity_list_repos_starred_by_user.go | 99 + .../activity_list_repos_watched_by_user.go | 91 + .../activity_list_stargazers_for_repo.go | 100 + ...st_watched_repos_for_authenticated_user.go | 82 + .../activity_list_watchers_for_repo.go | 100 + .../activity_mark_notifications_as_read.go | 88 + ...ctivity_mark_repo_notifications_as_read.go | 105 + .../activity/activity_mark_thread_as_done.go | 77 + .../activity/activity_mark_thread_as_read.go | 77 + .../activity_set_repo_subscription.go | 106 + .../activity_set_thread_subscription.go | 96 + ...tivity_star_repo_for_authenticated_user.go | 86 + ...vity_unstar_repo_for_authenticated_user.go | 86 + ..._to_installation_for_authenticated_user.go | 86 + MCP/tools/apps/apps_check_token.go | 96 + MCP/tools/apps/apps_create_from_manifest.go | 77 + .../apps_create_installation_access_token.go | 98 + MCP/tools/apps/apps_delete_authorization.go | 96 + MCP/tools/apps/apps_delete_installation.go | 77 + MCP/tools/apps/apps_delete_token.go | 96 + MCP/tools/apps/apps_get_authenticated.go | 64 + MCP/tools/apps/apps_get_by_slug.go | 77 + MCP/tools/apps/apps_get_installation.go | 77 + MCP/tools/apps/apps_get_org_installation.go | 77 + MCP/tools/apps/apps_get_repo_installation.go | 86 + .../apps_get_subscription_plan_for_account.go | 77 + ...t_subscription_plan_for_account_stubbed.go | 77 + MCP/tools/apps/apps_get_user_installation.go | 77 + .../apps/apps_get_webhook_config_for_app.go | 64 + MCP/tools/apps/apps_get_webhook_delivery.go | 77 + MCP/tools/apps/apps_list_accounts_for_plan.go | 99 + .../apps_list_accounts_for_plan_stubbed.go | 99 + ...stallation_repos_for_authenticated_user.go | 91 + ...allation_requests_for_authenticated_app.go | 82 + MCP/tools/apps/apps_list_installations.go | 90 + ...st_installations_for_authenticated_user.go | 82 + MCP/tools/apps/apps_list_plans.go | 82 + MCP/tools/apps/apps_list_plans_stubbed.go | 82 + ...s_list_repos_accessible_to_installation.go | 82 + ...st_subscriptions_for_authenticated_user.go | 82 + ...riptions_for_authenticated_user_stubbed.go | 82 + .../apps/apps_list_webhook_deliveries.go | 82 + .../apps/apps_redeliver_webhook_delivery.go | 77 + ...rom_installation_for_authenticated_user.go | 86 + MCP/tools/apps/apps_reset_token.go | 96 + .../apps_revoke_installation_access_token.go | 64 + MCP/tools/apps/apps_scope_token.go | 101 + MCP/tools/apps/apps_suspend_installation.go | 77 + MCP/tools/apps/apps_unsuspend_installation.go | 77 + .../apps_update_webhook_config_for_app.go | 90 + .../billing_get_github_actions_billing_org.go | 77 + ...billing_get_github_actions_billing_user.go | 77 + ...ing_get_github_billing_usage_report_org.go | 99 + ...ng_get_github_billing_usage_report_user.go | 99 + ...billing_get_github_packages_billing_org.go | 77 + ...illing_get_github_packages_billing_user.go | 77 + .../billing_get_shared_storage_billing_org.go | 77 + ...billing_get_shared_storage_billing_user.go | 77 + .../campaigns/campaigns_create_campaign.go | 103 + .../campaigns/campaigns_delete_campaign.go | 86 + .../campaigns_get_campaign_summary.go | 86 + .../campaigns/campaigns_list_org_campaigns.go | 103 + .../campaigns/campaigns_update_campaign.go | 111 + MCP/tools/checks/checks_create.go | 114 + MCP/tools/checks/checks_create_suite.go | 105 + MCP/tools/checks/checks_get.go | 95 + MCP/tools/checks/checks_get_suite.go | 95 + MCP/tools/checks/checks_list_annotations.go | 109 + MCP/tools/checks/checks_list_for_ref.go | 125 + MCP/tools/checks/checks_list_for_suite.go | 121 + .../checks/checks_list_suites_for_ref.go | 117 + MCP/tools/checks/checks_rerequest_run.go | 95 + MCP/tools/checks/checks_rerequest_suite.go | 95 + .../checks/checks_set_suites_preferences.go | 105 + MCP/tools/checks/checks_update.go | 122 + .../classroom/classroom_get_a_classroom.go | 77 + .../classroom/classroom_get_an_assignment.go | 77 + .../classroom_get_assignment_grades.go | 77 + ..._accepted_assignments_for_an_assignment.go | 91 + ...ssroom_list_assignments_for_a_classroom.go | 91 + .../classroom/classroom_list_classrooms.go | 82 + .../code_scanning_commit_autofix.go | 115 + .../code_scanning_create_autofix.go | 95 + .../code_scanning_create_variant_analysis.go | 109 + .../code_scanning_delete_analysis.go | 105 + .../code_scanning_delete_codeql_database.go | 95 + .../code_scanning/code_scanning_get_alert.go | 95 + .../code_scanning_get_analysis.go | 95 + .../code_scanning_get_autofix.go | 95 + .../code_scanning_get_codeql_database.go | 95 + .../code_scanning_get_default_setup.go | 86 + .../code_scanning/code_scanning_get_sarif.go | 95 + .../code_scanning_get_variant_analysis.go | 95 + ...scanning_get_variant_analysis_repo_task.go | 113 + .../code_scanning_list_alert_instances.go | 117 + .../code_scanning_list_alerts_for_org.go | 123 + .../code_scanning_list_alerts_for_repo.go | 140 + .../code_scanning_list_codeql_databases.go | 86 + .../code_scanning_list_recent_analyses.go | 128 + .../code_scanning_update_alert.go | 117 + .../code_scanning_update_default_setup.go | 110 + .../code_scanning_upload_sarif.go | 111 + .../code_security_attach_configuration.go | 106 + ...ecurity_attach_enterprise_configuration.go | 105 + .../code_security_create_configuration.go | 116 + ...ity_create_configuration_for_enterprise.go | 114 + .../code_security_delete_configuration.go | 86 + ...ity_delete_configuration_for_enterprise.go | 86 + .../code_security_detach_configuration.go | 96 + .../code_security_get_configuration.go | 86 + ...curity_get_configuration_for_repository.go | 86 + ...urity_get_configurations_for_enterprise.go | 95 + ...ode_security_get_configurations_for_org.go | 99 + ...ode_security_get_default_configurations.go | 77 + ...t_default_configurations_for_enterprise.go | 77 + ...rity_get_repositories_for_configuration.go | 108 + ...positories_for_enterprise_configuration.go | 108 + ...get_single_configuration_for_enterprise.go | 86 + ...e_security_set_configuration_as_default.go | 105 + ...configuration_as_default_for_enterprise.go | 105 + .../code_security_update_configuration.go | 125 + ...ecurity_update_enterprise_configuration.go | 123 + ...des_of_conduct_get_all_codes_of_conduct.go | 64 + .../codes_of_conduct_get_conduct_code.go | 77 + ...itory_for_secret_for_authenticated_user.go | 86 + ...espaces_add_selected_repo_to_org_secret.go | 95 + ...aces_check_permissions_for_devcontainer.go | 100 + ...despace_machines_for_authenticated_user.go | 77 + ...odespaces_create_for_authenticated_user.go | 86 + .../codespaces_create_or_update_org_secret.go | 108 + ...codespaces_create_or_update_repo_secret.go | 115 + ...or_update_secret_for_authenticated_user.go | 98 + ...s_create_with_pr_for_authenticated_user.go | 123 + ...create_with_repo_for_authenticated_user.go | 115 + ...despaces_delete_codespaces_access_users.go | 96 + ...odespaces_delete_for_authenticated_user.go | 77 + .../codespaces_delete_from_organization.go | 95 + .../codespaces_delete_org_secret.go | 86 + .../codespaces_delete_repo_secret.go | 95 + ...es_delete_secret_for_authenticated_user.go | 77 + ...odespaces_export_for_authenticated_user.go | 77 + ...despaces_get_codespaces_for_user_in_org.go | 100 + ...t_export_details_for_authenticated_user.go | 86 + .../codespaces_get_for_authenticated_user.go | 77 + .../codespaces_get_org_public_key.go | 77 + .../codespaces/codespaces_get_org_secret.go | 86 + ...s_get_public_key_for_authenticated_user.go | 64 + .../codespaces_get_repo_public_key.go | 86 + .../codespaces/codespaces_get_repo_secret.go | 95 + ...paces_get_secret_for_authenticated_user.go | 77 + ...rs_in_repository_for_authenticated_user.go | 100 + .../codespaces_list_for_authenticated_user.go | 86 + .../codespaces_list_in_organization.go | 91 + ...st_in_repository_for_authenticated_user.go | 100 + .../codespaces/codespaces_list_org_secrets.go | 91 + .../codespaces_list_repo_secrets.go | 100 + ...ories_for_secret_for_authenticated_user.go | 77 + ...ces_list_secrets_for_authenticated_user.go | 82 + ...aces_list_selected_repos_for_org_secret.go | 100 + ...flight_with_repo_for_authenticated_user.go | 100 + ...despaces_publish_for_authenticated_user.go | 97 + ...itory_for_secret_for_authenticated_user.go | 86 + ...es_remove_selected_repo_from_org_secret.go | 95 + ...es_repo_machines_for_authenticated_user.go | 104 + .../codespaces_set_codespaces_access.go | 97 + .../codespaces_set_codespaces_access_users.go | 96 + ...ories_for_secret_for_authenticated_user.go | 96 + ...paces_set_selected_repos_for_org_secret.go | 105 + ...codespaces_start_for_authenticated_user.go | 77 + .../codespaces_stop_for_authenticated_user.go | 77 + .../codespaces_stop_in_organization.go | 95 + ...odespaces_update_for_authenticated_user.go | 98 + .../copilot_add_copilot_seats_for_teams.go | 96 + .../copilot_add_copilot_seats_for_users.go | 96 + ...ancel_copilot_seat_assignment_for_teams.go | 96 + ...ancel_copilot_seat_assignment_for_users.go | 96 + ...opilot_copilot_metrics_for_organization.go | 99 + .../copilot_copilot_metrics_for_team.go | 108 + ...opilot_get_copilot_organization_details.go | 77 + ...pilot_get_copilot_seat_details_for_user.go | 86 + .../copilot/copilot_list_copilot_seats.go | 91 + MCP/tools/credentials/credentials_revoke.go | 87 + ...endabot_add_selected_repo_to_org_secret.go | 95 + .../dependabot_create_or_update_org_secret.go | 108 + ...dependabot_create_or_update_repo_secret.go | 115 + .../dependabot_delete_org_secret.go | 86 + .../dependabot_delete_repo_secret.go | 95 + MCP/tools/dependabot/dependabot_get_alert.go | 95 + .../dependabot_get_org_public_key.go | 77 + .../dependabot/dependabot_get_org_secret.go | 86 + .../dependabot_get_repo_public_key.go | 86 + .../dependabot/dependabot_get_repo_secret.go | 95 + .../dependabot_list_alerts_for_enterprise.go | 139 + .../dependabot_list_alerts_for_org.go | 139 + .../dependabot_list_alerts_for_repo.go | 156 + .../dependabot/dependabot_list_org_secrets.go | 91 + .../dependabot_list_repo_secrets.go | 100 + ...abot_list_selected_repos_for_org_secret.go | 100 + ...ot_remove_selected_repo_from_org_secret.go | 95 + .../dependabot_repository_access_for_org.go | 91 + ...bot_set_repository_access_default_level.go | 96 + ...dabot_set_selected_repos_for_org_secret.go | 105 + .../dependabot/dependabot_update_alert.go | 116 + ...ndabot_update_repository_access_for_org.go | 97 + ...ndency_graph_create_repository_snapshot.go | 112 + .../dependency_graph_diff_range.go | 105 + .../dependency_graph_export_sbom.go | 86 + MCP/tools/emojis/emojis_get.go | 64 + MCP/tools/gists/gists_check_is_starred.go | 77 + MCP/tools/gists/gists_create.go | 89 + MCP/tools/gists/gists_create_comment.go | 96 + MCP/tools/gists/gists_delete.go | 77 + MCP/tools/gists/gists_delete_comment.go | 86 + MCP/tools/gists/gists_fork.go | 77 + MCP/tools/gists/gists_get.go | 77 + MCP/tools/gists/gists_get_comment.go | 86 + MCP/tools/gists/gists_get_revision.go | 86 + MCP/tools/gists/gists_list.go | 86 + MCP/tools/gists/gists_list_comments.go | 91 + MCP/tools/gists/gists_list_commits.go | 91 + MCP/tools/gists/gists_list_for_user.go | 95 + MCP/tools/gists/gists_list_forks.go | 91 + MCP/tools/gists/gists_list_public.go | 86 + MCP/tools/gists/gists_list_starred.go | 86 + MCP/tools/gists/gists_star.go | 77 + MCP/tools/gists/gists_unstar.go | 77 + MCP/tools/gists/gists_update.go | 97 + MCP/tools/gists/gists_update_comment.go | 105 + MCP/tools/git/git_create_blob.go | 106 + MCP/tools/git/git_create_commit.go | 110 + MCP/tools/git/git_create_ref.go | 106 + MCP/tools/git/git_create_tag.go | 109 + MCP/tools/git/git_create_tree.go | 106 + MCP/tools/git/git_delete_ref.go | 95 + MCP/tools/git/git_get_blob.go | 95 + MCP/tools/git/git_get_commit.go | 95 + MCP/tools/git/git_get_ref.go | 95 + MCP/tools/git/git_get_tag.go | 95 + MCP/tools/git/git_get_tree.go | 105 + MCP/tools/git/git_list_matching_refs.go | 95 + MCP/tools/git/git_update_ref.go | 115 + .../gitignore/gitignore_get_all_templates.go | 64 + MCP/tools/gitignore/gitignore_get_template.go | 77 + ...te_create_network_configuration_for_org.go | 98 + ...e_delete_network_configuration_from_org.go | 86 + ...mpute_get_network_configuration_for_org.go | 86 + ...ed_compute_get_network_settings_for_org.go | 86 + ...ute_list_network_configurations_for_org.go | 91 + ...te_update_network_configuration_for_org.go | 107 + ...get_restrictions_for_authenticated_user.go | 64 + .../interactions_get_restrictions_for_org.go | 77 + .../interactions_get_restrictions_for_repo.go | 86 + ...ove_restrictions_for_authenticated_user.go | 64 + ...nteractions_remove_restrictions_for_org.go | 77 + ...teractions_remove_restrictions_for_repo.go | 86 + ...set_restrictions_for_authenticated_user.go | 88 + .../interactions_set_restrictions_for_org.go | 97 + .../interactions_set_restrictions_for_repo.go | 106 + MCP/tools/issues/issues_add_assignees.go | 114 + MCP/tools/issues/issues_add_labels.go | 113 + MCP/tools/issues/issues_add_sub_issue.go | 115 + .../issues_check_user_can_be_assigned.go | 95 + ...ues_check_user_can_be_assigned_to_issue.go | 104 + MCP/tools/issues/issues_create.go | 111 + MCP/tools/issues/issues_create_comment.go | 114 + MCP/tools/issues/issues_create_label.go | 107 + MCP/tools/issues/issues_create_milestone.go | 108 + MCP/tools/issues/issues_delete_comment.go | 95 + MCP/tools/issues/issues_delete_label.go | 95 + MCP/tools/issues/issues_delete_milestone.go | 95 + MCP/tools/issues/issues_get.go | 95 + MCP/tools/issues/issues_get_comment.go | 95 + MCP/tools/issues/issues_get_event.go | 95 + MCP/tools/issues/issues_get_label.go | 95 + MCP/tools/issues/issues_get_milestone.go | 95 + MCP/tools/issues/issues_list.go | 122 + MCP/tools/issues/issues_list_assignees.go | 100 + MCP/tools/issues/issues_list_comments.go | 113 + .../issues/issues_list_comments_for_repo.go | 112 + MCP/tools/issues/issues_list_events.go | 109 + .../issues/issues_list_events_for_repo.go | 100 + .../issues/issues_list_events_for_timeline.go | 109 + .../issues_list_for_authenticated_user.go | 106 + MCP/tools/issues/issues_list_for_org.go | 119 + MCP/tools/issues/issues_list_for_repo.go | 140 + .../issues_list_labels_for_milestone.go | 109 + .../issues/issues_list_labels_for_repo.go | 100 + .../issues/issues_list_labels_on_issue.go | 109 + MCP/tools/issues/issues_list_milestones.go | 112 + MCP/tools/issues/issues_list_sub_issues.go | 109 + MCP/tools/issues/issues_lock.go | 114 + MCP/tools/issues/issues_remove_all_labels.go | 95 + MCP/tools/issues/issues_remove_assignees.go | 114 + MCP/tools/issues/issues_remove_label.go | 104 + MCP/tools/issues/issues_remove_sub_issue.go | 114 + .../issues/issues_reprioritize_sub_issue.go | 116 + MCP/tools/issues/issues_set_labels.go | 113 + MCP/tools/issues/issues_unlock.go | 95 + MCP/tools/issues/issues_update.go | 122 + MCP/tools/issues/issues_update_comment.go | 114 + MCP/tools/issues/issues_update_label.go | 116 + MCP/tools/issues/issues_update_milestone.go | 117 + MCP/tools/licenses/licenses_get.go | 77 + .../licenses_get_all_commonly_used.go | 86 + MCP/tools/licenses/licenses_get_for_repo.go | 96 + MCP/tools/meta/meta_get.go | 64 + MCP/tools/meta/meta_get_all_versions.go | 64 + MCP/tools/meta/meta_get_zen.go | 64 + MCP/tools/meta/meta_root.go | 64 + .../migrations/migrations_cancel_import.go | 86 + ...s_delete_archive_for_authenticated_user.go | 77 + .../migrations_delete_archive_for_org.go | 86 + .../migrations_download_archive_for_org.go | 86 + ...ions_get_archive_for_authenticated_user.go | 77 + .../migrations_get_commit_authors.go | 96 + .../migrations_get_import_status.go | 86 + .../migrations/migrations_get_large_files.go | 86 + ...tions_get_status_for_authenticated_user.go | 87 + .../migrations_get_status_for_org.go | 96 + .../migrations_list_for_authenticated_user.go | 82 + .../migrations/migrations_list_for_org.go | 95 + ...tions_list_repos_for_authenticated_user.go | 91 + .../migrations_list_repos_for_org.go | 100 + .../migrations_map_commit_author.go | 115 + .../migrations_set_lfs_preference.go | 105 + ...migrations_start_for_authenticated_user.go | 95 + .../migrations/migrations_start_for_org.go | 104 + .../migrations/migrations_start_import.go | 109 + ...ions_unlock_repo_for_authenticated_user.go | 86 + .../migrations_unlock_repo_for_org.go | 95 + .../migrations/migrations_update_import.go | 108 + ...dc_get_oidc_custom_sub_template_for_org.go | 77 + ...update_oidc_custom_sub_template_for_org.go | 96 + .../api_insights_get_route_stats_by_actor.go | 129 + .../orgs/api_insights_get_subject_stats.go | 111 + .../orgs/api_insights_get_summary_stats.go | 91 + ...api_insights_get_summary_stats_by_actor.go | 109 + .../api_insights_get_summary_stats_by_user.go | 100 + MCP/tools/orgs/api_insights_get_time_stats.go | 95 + .../api_insights_get_time_stats_by_actor.go | 113 + .../api_insights_get_time_stats_by_user.go | 104 + MCP/tools/orgs/api_insights_get_user_stats.go | 120 + .../orgs/orgs_add_security_manager_team.go | 86 + .../orgs/orgs_assign_team_to_org_role.go | 95 + .../orgs/orgs_assign_user_to_org_role.go | 95 + MCP/tools/orgs/orgs_block_user.go | 86 + MCP/tools/orgs/orgs_cancel_invitation.go | 86 + MCP/tools/orgs/orgs_check_blocked_user.go | 86 + .../orgs/orgs_check_membership_for_user.go | 86 + .../orgs_check_public_membership_for_user.go | 86 + ..._convert_member_to_outside_collaborator.go | 105 + MCP/tools/orgs/orgs_create_invitation.go | 99 + MCP/tools/orgs/orgs_create_issue_type.go | 99 + ...orgs_create_or_update_custom_properties.go | 96 + ...date_custom_properties_values_for_repos.go | 97 + .../orgs_create_or_update_custom_property.go | 110 + MCP/tools/orgs/orgs_create_webhook.go | 99 + MCP/tools/orgs/orgs_delete.go | 77 + .../orgs/orgs_delete_attestations_bulk.go | 95 + .../orgs/orgs_delete_attestations_by_id.go | 86 + ...s_delete_attestations_by_subject_digest.go | 86 + MCP/tools/orgs/orgs_delete_issue_type.go | 86 + MCP/tools/orgs/orgs_delete_webhook.go | 86 + ...sable_security_product_on_all_org_repos.go | 114 + MCP/tools/orgs/orgs_get.go | 77 + .../orgs/orgs_get_all_custom_properties.go | 77 + MCP/tools/orgs/orgs_get_custom_property.go | 86 + ...s_get_membership_for_authenticated_user.go | 77 + .../orgs/orgs_get_membership_for_user.go | 86 + MCP/tools/orgs/orgs_get_org_role.go | 86 + .../orgs/orgs_get_org_ruleset_history.go | 100 + .../orgs/orgs_get_org_ruleset_version.go | 95 + MCP/tools/orgs/orgs_get_webhook.go | 86 + .../orgs/orgs_get_webhook_config_for_org.go | 86 + MCP/tools/orgs/orgs_get_webhook_delivery.go | 95 + MCP/tools/orgs/orgs_list.go | 82 + MCP/tools/orgs/orgs_list_app_installations.go | 91 + MCP/tools/orgs/orgs_list_attestations.go | 108 + MCP/tools/orgs/orgs_list_attestations_bulk.go | 115 + MCP/tools/orgs/orgs_list_blocked_users.go | 91 + ...list_custom_properties_values_for_repos.go | 95 + .../orgs/orgs_list_failed_invitations.go | 91 + .../orgs/orgs_list_for_authenticated_user.go | 82 + MCP/tools/orgs/orgs_list_for_user.go | 91 + MCP/tools/orgs/orgs_list_invitation_teams.go | 100 + MCP/tools/orgs/orgs_list_issue_types.go | 77 + MCP/tools/orgs/orgs_list_members.go | 99 + ...list_memberships_for_authenticated_user.go | 86 + MCP/tools/orgs/orgs_list_org_role_teams.go | 100 + MCP/tools/orgs/orgs_list_org_role_users.go | 100 + MCP/tools/orgs/orgs_list_org_roles.go | 77 + .../orgs/orgs_list_outside_collaborators.go | 95 + .../orgs/orgs_list_pat_grant_repositories.go | 100 + ...rgs_list_pat_grant_request_repositories.go | 100 + .../orgs/orgs_list_pat_grant_requests.go | 123 + MCP/tools/orgs/orgs_list_pat_grants.go | 123 + .../orgs/orgs_list_pending_invitations.go | 99 + MCP/tools/orgs/orgs_list_public_members.go | 91 + .../orgs/orgs_list_security_manager_teams.go | 77 + .../orgs/orgs_list_webhook_deliveries.go | 100 + MCP/tools/orgs/orgs_list_webhooks.go | 91 + MCP/tools/orgs/orgs_ping_webhook.go | 86 + .../orgs/orgs_redeliver_webhook_delivery.go | 95 + MCP/tools/orgs/orgs_remove_custom_property.go | 86 + MCP/tools/orgs/orgs_remove_member.go | 86 + .../orgs/orgs_remove_membership_for_user.go | 86 + .../orgs/orgs_remove_outside_collaborator.go | 86 + ...ublic_membership_for_authenticated_user.go | 86 + .../orgs/orgs_remove_security_manager_team.go | 86 + .../orgs/orgs_review_pat_grant_request.go | 106 + .../orgs_review_pat_grant_requests_in_bulk.go | 98 + .../orgs/orgs_revoke_all_org_roles_team.go | 86 + .../orgs/orgs_revoke_all_org_roles_user.go | 86 + MCP/tools/orgs/orgs_revoke_org_role_team.go | 95 + MCP/tools/orgs/orgs_revoke_org_role_user.go | 95 + .../orgs/orgs_set_membership_for_user.go | 105 + ...ublic_membership_for_authenticated_user.go | 86 + MCP/tools/orgs/orgs_unblock_user.go | 86 + MCP/tools/orgs/orgs_update.go | 125 + MCP/tools/orgs/orgs_update_issue_type.go | 108 + ...pdate_membership_for_authenticated_user.go | 96 + MCP/tools/orgs/orgs_update_pat_access.go | 105 + MCP/tools/orgs/orgs_update_pat_accesses.go | 97 + MCP/tools/orgs/orgs_update_webhook.go | 108 + .../orgs_update_webhook_config_for_org.go | 108 + ...s_delete_package_for_authenticated_user.go | 86 + .../packages_delete_package_for_org.go | 95 + .../packages_delete_package_for_user.go | 95 + ..._package_version_for_authenticated_user.go | 95 + ...packages_delete_package_version_for_org.go | 104 + ...ackages_delete_package_version_for_user.go | 104 + ...for_package_owned_by_authenticated_user.go | 104 + ...ckage_versions_for_package_owned_by_org.go | 113 + ...kage_versions_for_package_owned_by_user.go | 95 + ...ages_get_package_for_authenticated_user.go | 86 + .../packages_get_package_for_organization.go | 95 + .../packages/packages_get_package_for_user.go | 95 + ..._package_version_for_authenticated_user.go | 95 + ...es_get_package_version_for_organization.go | 104 + .../packages_get_package_version_for_user.go | 104 + ...licting_packages_for_authenticated_user.go | 64 + ...n_conflicting_packages_for_organization.go | 77 + ...migration_conflicting_packages_for_user.go | 77 + ...es_list_packages_for_authenticated_user.go | 90 + ...packages_list_packages_for_organization.go | 99 + .../packages_list_packages_for_user.go | 99 + ..._restore_package_for_authenticated_user.go | 96 + .../packages_restore_package_for_org.go | 105 + .../packages_restore_package_for_user.go | 105 + ..._package_version_for_authenticated_user.go | 95 + ...ackages_restore_package_version_for_org.go | 104 + ...ckages_restore_package_version_for_user.go | 104 + ..._registries_create_org_private_registry.go | 102 + ..._registries_delete_org_private_registry.go | 86 + ...ate_registries_get_org_private_registry.go | 86 + .../private_registries_get_org_public_key.go | 77 + ..._registries_list_org_private_registries.go | 91 + ..._registries_update_org_private_registry.go | 111 + .../projects/projects_add_collaborator.go | 105 + MCP/tools/projects/projects_create_card.go | 95 + MCP/tools/projects/projects_create_column.go | 96 + .../projects_create_for_authenticated_user.go | 88 + MCP/tools/projects/projects_create_for_org.go | 97 + .../projects/projects_create_for_repo.go | 106 + MCP/tools/projects/projects_delete.go | 77 + MCP/tools/projects/projects_delete_card.go | 77 + MCP/tools/projects/projects_delete_column.go | 77 + MCP/tools/projects/projects_get.go | 77 + MCP/tools/projects/projects_get_card.go | 77 + MCP/tools/projects/projects_get_column.go | 77 + .../projects_get_permission_for_user.go | 86 + MCP/tools/projects/projects_list_cards.go | 95 + .../projects/projects_list_collaborators.go | 95 + MCP/tools/projects/projects_list_columns.go | 91 + MCP/tools/projects/projects_list_for_org.go | 95 + MCP/tools/projects/projects_list_for_repo.go | 104 + MCP/tools/projects/projects_list_for_user.go | 95 + MCP/tools/projects/projects_move_card.go | 97 + MCP/tools/projects/projects_move_column.go | 96 + .../projects/projects_remove_collaborator.go | 86 + MCP/tools/projects/projects_update.go | 100 + MCP/tools/projects/projects_update_card.go | 97 + MCP/tools/projects/projects_update_column.go | 96 + MCP/tools/pulls/pulls_check_if_merged.go | 95 + MCP/tools/pulls/pulls_create.go | 112 + .../pulls_create_reply_for_review_comment.go | 123 + MCP/tools/pulls/pulls_create_review.go | 117 + .../pulls/pulls_create_review_comment.go | 123 + .../pulls/pulls_delete_pending_review.go | 104 + .../pulls/pulls_delete_review_comment.go | 95 + MCP/tools/pulls/pulls_dismiss_review.go | 124 + MCP/tools/pulls/pulls_get.go | 95 + MCP/tools/pulls/pulls_get_review.go | 104 + MCP/tools/pulls/pulls_get_review_comment.go | 95 + MCP/tools/pulls/pulls_list.go | 120 + .../pulls/pulls_list_comments_for_review.go | 118 + MCP/tools/pulls/pulls_list_commits.go | 109 + MCP/tools/pulls/pulls_list_files.go | 109 + .../pulls/pulls_list_requested_reviewers.go | 95 + MCP/tools/pulls/pulls_list_review_comments.go | 121 + .../pulls_list_review_comments_for_repo.go | 112 + MCP/tools/pulls/pulls_list_reviews.go | 109 + MCP/tools/pulls/pulls_merge.go | 117 + .../pulls/pulls_remove_requested_reviewers.go | 115 + MCP/tools/pulls/pulls_request_reviewers.go | 115 + MCP/tools/pulls/pulls_submit_review.go | 124 + MCP/tools/pulls/pulls_update.go | 118 + MCP/tools/pulls/pulls_update_branch.go | 114 + MCP/tools/pulls/pulls_update_review.go | 123 + .../pulls/pulls_update_review_comment.go | 114 + MCP/tools/rate_limit/rate_limit_get.go | 64 + .../reactions_create_for_commit_comment.go | 114 + .../reactions/reactions_create_for_issue.go | 114 + .../reactions_create_for_issue_comment.go | 114 + ..._create_for_pull_request_review_comment.go | 114 + .../reactions/reactions_create_for_release.go | 114 + ...eate_for_team_discussion_comment_in_org.go | 123 + ...eate_for_team_discussion_comment_legacy.go | 114 + ...tions_create_for_team_discussion_in_org.go | 114 + ...tions_create_for_team_discussion_legacy.go | 105 + .../reactions_delete_for_commit_comment.go | 104 + .../reactions/reactions_delete_for_issue.go | 104 + .../reactions_delete_for_issue_comment.go | 104 + ...actions_delete_for_pull_request_comment.go | 104 + .../reactions/reactions_delete_for_release.go | 104 + .../reactions_delete_for_team_discussion.go | 104 + ...ions_delete_for_team_discussion_comment.go | 113 + .../reactions_list_for_commit_comment.go | 113 + .../reactions/reactions_list_for_issue.go | 113 + .../reactions_list_for_issue_comment.go | 113 + ...ns_list_for_pull_request_review_comment.go | 113 + .../reactions/reactions_list_for_release.go | 113 + ...list_for_team_discussion_comment_in_org.go | 122 + ...list_for_team_discussion_comment_legacy.go | 113 + ...actions_list_for_team_discussion_in_org.go | 113 + ...actions_list_for_team_discussion_legacy.go | 104 + ...ccept_invitation_for_authenticated_user.go | 77 + .../repos_add_app_access_restrictions.go | 114 + MCP/tools/repos/repos_add_collaborator.go | 114 + .../repos/repos_add_status_check_contexts.go | 113 + .../repos_add_team_access_restrictions.go | 113 + .../repos_add_user_access_restrictions.go | 114 + .../repos/repos_cancel_pages_deployment.go | 95 + .../repos_check_automated_security_fixes.go | 86 + MCP/tools/repos/repos_check_collaborator.go | 95 + ...s_check_private_vulnerability_reporting.go | 86 + .../repos/repos_check_vulnerability_alerts.go | 86 + MCP/tools/repos/repos_codeowners_errors.go | 96 + MCP/tools/repos/repos_compare_commits.go | 109 + MCP/tools/repos/repos_create_attestation.go | 105 + MCP/tools/repos/repos_create_autolink.go | 107 + .../repos/repos_create_commit_comment.go | 117 + ...epos_create_commit_signature_protection.go | 95 + MCP/tools/repos/repos_create_commit_status.go | 117 + MCP/tools/repos/repos_create_deploy_key.go | 107 + MCP/tools/repos/repos_create_deployment.go | 113 + .../repos_create_deployment_branch_policy.go | 115 + ...repos_create_deployment_protection_rule.go | 114 + .../repos/repos_create_deployment_status.go | 120 + .../repos/repos_create_dispatch_event.go | 106 + .../repos_create_for_authenticated_user.go | 109 + MCP/tools/repos/repos_create_fork.go | 107 + MCP/tools/repos/repos_create_in_org.go | 120 + ...eate_or_update_custom_properties_values.go | 105 + .../repos_create_or_update_environment.go | 117 + .../repos_create_or_update_file_contents.go | 119 + MCP/tools/repos/repos_create_org_ruleset.go | 101 + .../repos/repos_create_pages_deployment.go | 109 + MCP/tools/repos/repos_create_pages_site.go | 106 + MCP/tools/repos/repos_create_release.go | 113 + MCP/tools/repos/repos_create_repo_ruleset.go | 110 + .../repos/repos_create_tag_protection.go | 105 + .../repos/repos_create_using_template.go | 109 + MCP/tools/repos/repos_create_webhook.go | 108 + ...cline_invitation_for_authenticated_user.go | 77 + MCP/tools/repos/repos_delete.go | 86 + .../repos/repos_delete_access_restrictions.go | 95 + .../repos_delete_admin_branch_protection.go | 95 + .../repos/repos_delete_an_environment.go | 95 + MCP/tools/repos/repos_delete_autolink.go | 95 + .../repos/repos_delete_branch_protection.go | 95 + .../repos/repos_delete_commit_comment.go | 95 + ...epos_delete_commit_signature_protection.go | 95 + MCP/tools/repos/repos_delete_deploy_key.go | 95 + MCP/tools/repos/repos_delete_deployment.go | 95 + .../repos_delete_deployment_branch_policy.go | 104 + MCP/tools/repos/repos_delete_file.go | 118 + MCP/tools/repos/repos_delete_invitation.go | 95 + MCP/tools/repos/repos_delete_org_ruleset.go | 86 + MCP/tools/repos/repos_delete_pages_site.go | 86 + ...s_delete_pull_request_review_protection.go | 95 + MCP/tools/repos/repos_delete_release.go | 95 + MCP/tools/repos/repos_delete_release_asset.go | 95 + MCP/tools/repos/repos_delete_repo_ruleset.go | 95 + .../repos/repos_delete_tag_protection.go | 95 + MCP/tools/repos/repos_delete_webhook.go | 95 + .../repos_disable_automated_security_fixes.go | 86 + ...epos_disable_deployment_protection_rule.go | 104 + ...disable_private_vulnerability_reporting.go | 86 + .../repos_disable_vulnerability_alerts.go | 86 + .../repos/repos_download_tarball_archive.go | 95 + .../repos/repos_download_zipball_archive.go | 95 + .../repos_enable_automated_security_fixes.go | 86 + ..._enable_private_vulnerability_reporting.go | 86 + .../repos_enable_vulnerability_alerts.go | 86 + .../repos/repos_generate_release_notes.go | 108 + MCP/tools/repos/repos_get.go | 86 + .../repos/repos_get_access_restrictions.go | 95 + .../repos_get_admin_branch_protection.go | 95 + ...pos_get_all_deployment_protection_rules.go | 95 + MCP/tools/repos/repos_get_all_environments.go | 100 + .../repos_get_all_status_check_contexts.go | 95 + MCP/tools/repos/repos_get_all_topics.go | 100 + ...et_apps_with_access_to_protected_branch.go | 95 + MCP/tools/repos/repos_get_autolink.go | 95 + MCP/tools/repos/repos_get_branch.go | 95 + .../repos/repos_get_branch_protection.go | 95 + MCP/tools/repos/repos_get_branch_rules.go | 109 + MCP/tools/repos/repos_get_clones.go | 96 + .../repos/repos_get_code_frequency_stats.go | 86 + ...repos_get_collaborator_permission_level.go | 95 + .../repos_get_combined_status_for_ref.go | 109 + MCP/tools/repos/repos_get_commit.go | 109 + .../repos/repos_get_commit_activity_stats.go | 86 + MCP/tools/repos/repos_get_commit_comment.go | 95 + .../repos_get_commit_signature_protection.go | 95 + .../repos_get_community_profile_metrics.go | 86 + MCP/tools/repos/repos_get_content.go | 105 + .../repos/repos_get_contributors_stats.go | 86 + ...s_get_custom_deployment_protection_rule.go | 104 + .../repos_get_custom_properties_values.go | 86 + MCP/tools/repos/repos_get_deploy_key.go | 95 + MCP/tools/repos/repos_get_deployment.go | 95 + .../repos_get_deployment_branch_policy.go | 104 + .../repos/repos_get_deployment_status.go | 104 + MCP/tools/repos/repos_get_environment.go | 95 + .../repos/repos_get_latest_pages_build.go | 86 + MCP/tools/repos/repos_get_latest_release.go | 86 + MCP/tools/repos/repos_get_org_rule_suite.go | 86 + MCP/tools/repos/repos_get_org_rule_suites.go | 111 + MCP/tools/repos/repos_get_org_ruleset.go | 86 + MCP/tools/repos/repos_get_org_rulesets.go | 95 + MCP/tools/repos/repos_get_pages.go | 86 + MCP/tools/repos/repos_get_pages_build.go | 95 + MCP/tools/repos/repos_get_pages_deployment.go | 95 + .../repos/repos_get_pages_health_check.go | 86 + .../repos/repos_get_participation_stats.go | 86 + ...epos_get_pull_request_review_protection.go | 95 + MCP/tools/repos/repos_get_punch_card_stats.go | 86 + MCP/tools/repos/repos_get_readme.go | 96 + .../repos/repos_get_readme_in_directory.go | 105 + MCP/tools/repos/repos_get_release.go | 95 + MCP/tools/repos/repos_get_release_asset.go | 95 + MCP/tools/repos/repos_get_release_by_tag.go | 95 + MCP/tools/repos/repos_get_repo_rule_suite.go | 95 + MCP/tools/repos/repos_get_repo_rule_suites.go | 116 + MCP/tools/repos/repos_get_repo_ruleset.go | 105 + .../repos/repos_get_repo_ruleset_history.go | 109 + .../repos/repos_get_repo_ruleset_version.go | 104 + MCP/tools/repos/repos_get_repo_rulesets.go | 108 + .../repos_get_status_checks_protection.go | 95 + ...t_teams_with_access_to_protected_branch.go | 95 + MCP/tools/repos/repos_get_top_paths.go | 86 + MCP/tools/repos/repos_get_top_referrers.go | 86 + ...t_users_with_access_to_protected_branch.go | 95 + MCP/tools/repos/repos_get_views.go | 96 + MCP/tools/repos/repos_get_webhook.go | 95 + .../repos_get_webhook_config_for_repo.go | 95 + MCP/tools/repos/repos_get_webhook_delivery.go | 104 + MCP/tools/repos/repos_list_activities.go | 124 + MCP/tools/repos/repos_list_attestations.go | 117 + MCP/tools/repos/repos_list_autolinks.go | 86 + MCP/tools/repos/repos_list_branches.go | 104 + .../repos_list_branches_for_head_commit.go | 95 + MCP/tools/repos/repos_list_collaborators.go | 108 + .../repos/repos_list_comments_for_commit.go | 109 + .../repos_list_commit_comments_for_repo.go | 100 + .../repos_list_commit_statuses_for_ref.go | 109 + MCP/tools/repos/repos_list_commits.go | 124 + MCP/tools/repos/repos_list_contributors.go | 104 + ...ist_custom_deployment_rule_integrations.go | 109 + MCP/tools/repos/repos_list_deploy_keys.go | 100 + .../repos_list_deployment_branch_policies.go | 109 + .../repos/repos_list_deployment_statuses.go | 109 + MCP/tools/repos/repos_list_deployments.go | 116 + .../repos_list_for_authenticated_user.go | 110 + MCP/tools/repos/repos_list_for_org.go | 103 + MCP/tools/repos/repos_list_for_user.go | 103 + MCP/tools/repos/repos_list_forks.go | 104 + MCP/tools/repos/repos_list_invitations.go | 100 + ...list_invitations_for_authenticated_user.go | 82 + MCP/tools/repos/repos_list_languages.go | 86 + MCP/tools/repos/repos_list_pages_builds.go | 100 + MCP/tools/repos/repos_list_public.go | 78 + ...st_pull_requests_associated_with_commit.go | 109 + MCP/tools/repos/repos_list_release_assets.go | 109 + MCP/tools/repos/repos_list_releases.go | 100 + MCP/tools/repos/repos_list_tag_protection.go | 86 + MCP/tools/repos/repos_list_tags.go | 100 + MCP/tools/repos/repos_list_teams.go | 100 + .../repos/repos_list_webhook_deliveries.go | 109 + MCP/tools/repos/repos_list_webhooks.go | 100 + MCP/tools/repos/repos_merge.go | 107 + MCP/tools/repos/repos_merge_upstream.go | 105 + MCP/tools/repos/repos_ping_webhook.go | 95 + .../repos/repos_redeliver_webhook_delivery.go | 104 + .../repos_remove_app_access_restrictions.go | 114 + MCP/tools/repos/repos_remove_collaborator.go | 95 + .../repos_remove_status_check_contexts.go | 113 + .../repos_remove_status_check_protection.go | 95 + .../repos_remove_team_access_restrictions.go | 113 + .../repos_remove_user_access_restrictions.go | 114 + MCP/tools/repos/repos_rename_branch.go | 114 + MCP/tools/repos/repos_replace_all_topics.go | 105 + MCP/tools/repos/repos_request_pages_build.go | 86 + .../repos_set_admin_branch_protection.go | 95 + .../repos_set_app_access_restrictions.go | 114 + .../repos/repos_set_status_check_contexts.go | 113 + .../repos_set_team_access_restrictions.go | 113 + .../repos_set_user_access_restrictions.go | 114 + MCP/tools/repos/repos_test_push_webhook.go | 95 + MCP/tools/repos/repos_transfer.go | 107 + MCP/tools/repos/repos_update.go | 129 + .../repos/repos_update_branch_protection.go | 124 + .../repos/repos_update_commit_comment.go | 114 + .../repos_update_deployment_branch_policy.go | 123 + ...pos_update_information_about_pages_site.go | 108 + MCP/tools/repos/repos_update_invitation.go | 114 + MCP/tools/repos/repos_update_org_ruleset.go | 110 + ...s_update_pull_request_review_protection.go | 119 + MCP/tools/repos/repos_update_release.go | 121 + MCP/tools/repos/repos_update_release_asset.go | 116 + MCP/tools/repos/repos_update_repo_ruleset.go | 119 + .../repos_update_status_check_protection.go | 116 + MCP/tools/repos/repos_update_webhook.go | 118 + .../repos_update_webhook_config_for_repo.go | 117 + MCP/tools/search/search_code.go | 94 + MCP/tools/search/search_commits.go | 94 + .../search/search_issues_and_pull_requests.go | 98 + MCP/tools/search/search_labels.go | 98 + MCP/tools/search/search_repos.go | 94 + MCP/tools/search/search_topics.go | 86 + MCP/tools/search/search_users.go | 94 + ..._scanning_create_push_protection_bypass.go | 106 + .../secret_scanning_get_alert.go | 105 + .../secret_scanning_get_scan_history.go | 86 + ...ret_scanning_list_alerts_for_enterprise.go | 131 + .../secret_scanning_list_alerts_for_org.go | 135 + .../secret_scanning_list_alerts_for_repo.go | 144 + ...ecret_scanning_list_locations_for_alert.go | 109 + .../secret_scanning_update_alert.go | 116 + .../security_advisories_create_fork.go | 95 + ...ies_create_private_vulnerability_report.go | 111 + ...y_advisories_create_repository_advisory.go | 113 + ..._create_repository_advisory_cve_request.go | 95 + ...security_advisories_get_global_advisory.go | 77 + ...rity_advisories_get_repository_advisory.go | 95 + ...urity_advisories_list_global_advisories.go | 146 + ...visories_list_org_repository_advisories.go | 107 + ...y_advisories_list_repository_advisories.go | 116 + ...y_advisories_update_repository_advisory.go | 124 + MCP/tools/teams/teams_add_member_legacy.go | 86 + ...dd_or_update_membership_for_user_in_org.go | 114 + ...dd_or_update_membership_for_user_legacy.go | 105 + ...dd_or_update_project_permissions_in_org.go | 114 + ...dd_or_update_project_permissions_legacy.go | 105 + ...s_add_or_update_repo_permissions_in_org.go | 123 + ...s_add_or_update_repo_permissions_legacy.go | 114 + ...ms_check_permissions_for_project_in_org.go | 95 + ...ms_check_permissions_for_project_legacy.go | 86 + ...teams_check_permissions_for_repo_in_org.go | 104 + ...teams_check_permissions_for_repo_legacy.go | 95 + MCP/tools/teams/teams_create.go | 103 + .../teams_create_discussion_comment_in_org.go | 114 + .../teams_create_discussion_comment_legacy.go | 105 + .../teams/teams_create_discussion_in_org.go | 107 + .../teams/teams_create_discussion_legacy.go | 98 + .../teams_delete_discussion_comment_in_org.go | 104 + .../teams_delete_discussion_comment_legacy.go | 95 + .../teams/teams_delete_discussion_in_org.go | 95 + .../teams/teams_delete_discussion_legacy.go | 86 + MCP/tools/teams/teams_delete_in_org.go | 86 + MCP/tools/teams/teams_delete_legacy.go | 77 + MCP/tools/teams/teams_get_by_name.go | 86 + .../teams_get_discussion_comment_in_org.go | 104 + .../teams_get_discussion_comment_legacy.go | 95 + .../teams/teams_get_discussion_in_org.go | 95 + .../teams/teams_get_discussion_legacy.go | 86 + MCP/tools/teams/teams_get_legacy.go | 77 + MCP/tools/teams/teams_get_member_legacy.go | 86 + .../teams_get_membership_for_user_in_org.go | 95 + .../teams_get_membership_for_user_legacy.go | 86 + MCP/tools/teams/teams_list.go | 91 + MCP/tools/teams/teams_list_child_in_org.go | 100 + MCP/tools/teams/teams_list_child_legacy.go | 91 + .../teams_list_discussion_comments_in_org.go | 113 + .../teams_list_discussion_comments_legacy.go | 104 + .../teams/teams_list_discussions_in_org.go | 108 + .../teams/teams_list_discussions_legacy.go | 95 + .../teams_list_for_authenticated_user.go | 82 + MCP/tools/teams/teams_list_members_in_org.go | 104 + MCP/tools/teams/teams_list_members_legacy.go | 95 + .../teams_list_pending_invitations_in_org.go | 100 + .../teams_list_pending_invitations_legacy.go | 91 + MCP/tools/teams/teams_list_projects_in_org.go | 100 + MCP/tools/teams/teams_list_projects_legacy.go | 91 + MCP/tools/teams/teams_list_repos_in_org.go | 100 + MCP/tools/teams/teams_list_repos_legacy.go | 91 + MCP/tools/teams/teams_remove_member_legacy.go | 86 + ...teams_remove_membership_for_user_in_org.go | 95 + ...teams_remove_membership_for_user_legacy.go | 86 + .../teams/teams_remove_project_in_org.go | 95 + .../teams/teams_remove_project_legacy.go | 86 + MCP/tools/teams/teams_remove_repo_in_org.go | 104 + MCP/tools/teams/teams_remove_repo_legacy.go | 95 + .../teams_update_discussion_comment_in_org.go | 123 + .../teams_update_discussion_comment_legacy.go | 114 + .../teams/teams_update_discussion_in_org.go | 115 + .../teams/teams_update_discussion_legacy.go | 106 + MCP/tools/teams/teams_update_in_org.go | 110 + MCP/tools/teams/teams_update_legacy.go | 101 + .../users_add_email_for_authenticated_user.go | 86 + ...d_social_account_for_authenticated_user.go | 87 + MCP/tools/users/users_block.go | 77 + MCP/tools/users/users_check_blocked.go | 77 + .../users/users_check_following_for_user.go | 86 + ...eck_person_is_followed_by_authenticated.go | 77 + ...s_create_gpg_key_for_authenticated_user.go | 88 + ...e_public_ssh_key_for_authenticated_user.go | 88 + ..._ssh_signing_key_for_authenticated_user.go | 88 + .../users/users_delete_attestations_bulk.go | 95 + .../users/users_delete_attestations_by_id.go | 86 + ...s_delete_attestations_by_subject_digest.go | 86 + ...ers_delete_email_for_authenticated_user.go | 86 + ...s_delete_gpg_key_for_authenticated_user.go | 77 + ...e_public_ssh_key_for_authenticated_user.go | 77 + ...e_social_account_for_authenticated_user.go | 87 + ..._ssh_signing_key_for_authenticated_user.go | 77 + MCP/tools/users/users_follow.go | 77 + MCP/tools/users/users_get_authenticated.go | 64 + MCP/tools/users/users_get_by_id.go | 77 + MCP/tools/users/users_get_by_username.go | 77 + MCP/tools/users/users_get_context_for_user.go | 91 + ...sers_get_gpg_key_for_authenticated_user.go | 77 + ...t_public_ssh_key_for_authenticated_user.go | 77 + ..._ssh_signing_key_for_authenticated_user.go | 77 + MCP/tools/users/users_list.go | 82 + MCP/tools/users/users_list_attestations.go | 108 + .../users/users_list_attestations_bulk.go | 115 + ...sers_list_blocked_by_authenticated_user.go | 82 + ...sers_list_emails_for_authenticated_user.go | 82 + ...ers_list_followed_by_authenticated_user.go | 82 + ...s_list_followers_for_authenticated_user.go | 82 + .../users/users_list_followers_for_user.go | 91 + .../users/users_list_following_for_user.go | 91 + ...rs_list_gpg_keys_for_authenticated_user.go | 82 + .../users/users_list_gpg_keys_for_user.go | 91 + ...st_public_emails_for_authenticated_user.go | 82 + .../users/users_list_public_keys_for_user.go | 91 + ..._public_ssh_keys_for_authenticated_user.go | 82 + ..._social_accounts_for_authenticated_user.go | 82 + .../users_list_social_accounts_for_user.go | 91 + ...ssh_signing_keys_for_authenticated_user.go | 82 + .../users_list_ssh_signing_keys_for_user.go | 91 + ...email_visibility_for_authenticated_user.go | 87 + MCP/tools/users/users_unblock.go | 77 + MCP/tools/users/users_unfollow.go | 77 + MCP/tools/users/users_update_authenticated.go | 94 + 1042 files changed, 112111 insertions(+) create mode 100644 MCP/README.md create mode 100644 MCP/config/config.go create mode 100644 MCP/go.mod create mode 100644 MCP/go.sum create mode 100644 MCP/main.go create mode 100644 MCP/models/models.go create mode 100644 MCP/registry.go create mode 100644 MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_repo.go create mode 100644 MCP/tools/actions/actions_add_repo_access_to_self_hosted_runner_group_in_org.go create mode 100644 MCP/tools/actions/actions_add_selected_repo_to_org_secret.go create mode 100644 MCP/tools/actions/actions_add_selected_repo_to_org_variable.go create mode 100644 MCP/tools/actions/actions_add_self_hosted_runner_to_group_for_org.go create mode 100644 MCP/tools/actions/actions_approve_workflow_run.go create mode 100644 MCP/tools/actions/actions_cancel_workflow_run.go create mode 100644 MCP/tools/actions/actions_create_environment_variable.go create mode 100644 MCP/tools/actions/actions_create_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_create_or_update_environment_secret.go create mode 100644 MCP/tools/actions/actions_create_or_update_org_secret.go create mode 100644 MCP/tools/actions/actions_create_or_update_repo_secret.go create mode 100644 MCP/tools/actions/actions_create_org_variable.go create mode 100644 MCP/tools/actions/actions_create_registration_token_for_org.go create mode 100644 MCP/tools/actions/actions_create_registration_token_for_repo.go create mode 100644 MCP/tools/actions/actions_create_remove_token_for_org.go create mode 100644 MCP/tools/actions/actions_create_remove_token_for_repo.go create mode 100644 MCP/tools/actions/actions_create_repo_variable.go create mode 100644 MCP/tools/actions/actions_create_self_hosted_runner_group_for_org.go create mode 100644 MCP/tools/actions/actions_create_workflow_dispatch.go create mode 100644 MCP/tools/actions/actions_delete_actions_cache_by_id.go create mode 100644 MCP/tools/actions/actions_delete_actions_cache_by_key.go create mode 100644 MCP/tools/actions/actions_delete_artifact.go create mode 100644 MCP/tools/actions/actions_delete_environment_secret.go create mode 100644 MCP/tools/actions/actions_delete_environment_variable.go create mode 100644 MCP/tools/actions/actions_delete_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_delete_org_secret.go create mode 100644 MCP/tools/actions/actions_delete_org_variable.go create mode 100644 MCP/tools/actions/actions_delete_repo_secret.go create mode 100644 MCP/tools/actions/actions_delete_repo_variable.go create mode 100644 MCP/tools/actions/actions_delete_self_hosted_runner_from_org.go create mode 100644 MCP/tools/actions/actions_delete_self_hosted_runner_from_repo.go create mode 100644 MCP/tools/actions/actions_delete_self_hosted_runner_group_from_org.go create mode 100644 MCP/tools/actions/actions_delete_workflow_run.go create mode 100644 MCP/tools/actions/actions_delete_workflow_run_logs.go create mode 100644 MCP/tools/actions/actions_disable_selected_repository_github_actions_organization.go create mode 100644 MCP/tools/actions/actions_disable_workflow.go create mode 100644 MCP/tools/actions/actions_download_artifact.go create mode 100644 MCP/tools/actions/actions_download_job_logs_for_workflow_run.go create mode 100644 MCP/tools/actions/actions_download_workflow_run_attempt_logs.go create mode 100644 MCP/tools/actions/actions_download_workflow_run_logs.go create mode 100644 MCP/tools/actions/actions_enable_selected_repository_github_actions_organization.go create mode 100644 MCP/tools/actions/actions_enable_workflow.go create mode 100644 MCP/tools/actions/actions_force_cancel_workflow_run.go create mode 100644 MCP/tools/actions/actions_generate_runner_jitconfig_for_org.go create mode 100644 MCP/tools/actions/actions_generate_runner_jitconfig_for_repo.go create mode 100644 MCP/tools/actions/actions_get_actions_cache_list.go create mode 100644 MCP/tools/actions/actions_get_actions_cache_usage.go create mode 100644 MCP/tools/actions/actions_get_actions_cache_usage_by_repo_for_org.go create mode 100644 MCP/tools/actions/actions_get_actions_cache_usage_for_org.go create mode 100644 MCP/tools/actions/actions_get_allowed_actions_organization.go create mode 100644 MCP/tools/actions/actions_get_allowed_actions_repository.go create mode 100644 MCP/tools/actions/actions_get_artifact.go create mode 100644 MCP/tools/actions/actions_get_custom_oidc_sub_claim_for_repo.go create mode 100644 MCP/tools/actions/actions_get_environment_public_key.go create mode 100644 MCP/tools/actions/actions_get_environment_secret.go create mode 100644 MCP/tools/actions/actions_get_environment_variable.go create mode 100644 MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_organization.go create mode 100644 MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_repository.go create mode 100644 MCP/tools/actions/actions_get_github_actions_permissions_organization.go create mode 100644 MCP/tools/actions/actions_get_github_actions_permissions_repository.go create mode 100644 MCP/tools/actions/actions_get_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_get_hosted_runners_github_owned_images_for_org.go create mode 100644 MCP/tools/actions/actions_get_hosted_runners_limits_for_org.go create mode 100644 MCP/tools/actions/actions_get_hosted_runners_machine_specs_for_org.go create mode 100644 MCP/tools/actions/actions_get_hosted_runners_partner_images_for_org.go create mode 100644 MCP/tools/actions/actions_get_hosted_runners_platforms_for_org.go create mode 100644 MCP/tools/actions/actions_get_job_for_workflow_run.go create mode 100644 MCP/tools/actions/actions_get_org_public_key.go create mode 100644 MCP/tools/actions/actions_get_org_secret.go create mode 100644 MCP/tools/actions/actions_get_org_variable.go create mode 100644 MCP/tools/actions/actions_get_pending_deployments_for_run.go create mode 100644 MCP/tools/actions/actions_get_repo_public_key.go create mode 100644 MCP/tools/actions/actions_get_repo_secret.go create mode 100644 MCP/tools/actions/actions_get_repo_variable.go create mode 100644 MCP/tools/actions/actions_get_reviews_for_run.go create mode 100644 MCP/tools/actions/actions_get_self_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_get_self_hosted_runner_for_repo.go create mode 100644 MCP/tools/actions/actions_get_self_hosted_runner_group_for_org.go create mode 100644 MCP/tools/actions/actions_get_workflow.go create mode 100644 MCP/tools/actions/actions_get_workflow_access_to_repository.go create mode 100644 MCP/tools/actions/actions_get_workflow_run.go create mode 100644 MCP/tools/actions/actions_get_workflow_run_attempt.go create mode 100644 MCP/tools/actions/actions_get_workflow_run_usage.go create mode 100644 MCP/tools/actions/actions_get_workflow_usage.go create mode 100644 MCP/tools/actions/actions_list_artifacts_for_repo.go create mode 100644 MCP/tools/actions/actions_list_environment_secrets.go create mode 100644 MCP/tools/actions/actions_list_environment_variables.go create mode 100644 MCP/tools/actions/actions_list_github_hosted_runners_in_group_for_org.go create mode 100644 MCP/tools/actions/actions_list_hosted_runners_for_org.go create mode 100644 MCP/tools/actions/actions_list_jobs_for_workflow_run.go create mode 100644 MCP/tools/actions/actions_list_jobs_for_workflow_run_attempt.go create mode 100644 MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_repo.go create mode 100644 MCP/tools/actions/actions_list_org_secrets.go create mode 100644 MCP/tools/actions/actions_list_org_variables.go create mode 100644 MCP/tools/actions/actions_list_repo_access_to_self_hosted_runner_group_in_org.go create mode 100644 MCP/tools/actions/actions_list_repo_organization_secrets.go create mode 100644 MCP/tools/actions/actions_list_repo_organization_variables.go create mode 100644 MCP/tools/actions/actions_list_repo_secrets.go create mode 100644 MCP/tools/actions/actions_list_repo_variables.go create mode 100644 MCP/tools/actions/actions_list_repo_workflows.go create mode 100644 MCP/tools/actions/actions_list_runner_applications_for_org.go create mode 100644 MCP/tools/actions/actions_list_runner_applications_for_repo.go create mode 100644 MCP/tools/actions/actions_list_selected_repos_for_org_secret.go create mode 100644 MCP/tools/actions/actions_list_selected_repos_for_org_variable.go create mode 100644 MCP/tools/actions/actions_list_selected_repositories_enabled_github_actions_organization.go create mode 100644 MCP/tools/actions/actions_list_self_hosted_runner_groups_for_org.go create mode 100644 MCP/tools/actions/actions_list_self_hosted_runners_for_org.go create mode 100644 MCP/tools/actions/actions_list_self_hosted_runners_for_repo.go create mode 100644 MCP/tools/actions/actions_list_self_hosted_runners_in_group_for_org.go create mode 100644 MCP/tools/actions/actions_list_workflow_run_artifacts.go create mode 100644 MCP/tools/actions/actions_list_workflow_runs.go create mode 100644 MCP/tools/actions/actions_list_workflow_runs_for_repo.go create mode 100644 MCP/tools/actions/actions_re_run_job_for_workflow_run.go create mode 100644 MCP/tools/actions/actions_re_run_workflow.go create mode 100644 MCP/tools/actions/actions_re_run_workflow_failed_jobs.go create mode 100644 MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_repo.go create mode 100644 MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_repo.go create mode 100644 MCP/tools/actions/actions_remove_repo_access_to_self_hosted_runner_group_in_org.go create mode 100644 MCP/tools/actions/actions_remove_selected_repo_from_org_secret.go create mode 100644 MCP/tools/actions/actions_remove_selected_repo_from_org_variable.go create mode 100644 MCP/tools/actions/actions_remove_self_hosted_runner_from_group_for_org.go create mode 100644 MCP/tools/actions/actions_review_custom_gates_for_run.go create mode 100644 MCP/tools/actions/actions_review_pending_deployments_for_run.go create mode 100644 MCP/tools/actions/actions_set_allowed_actions_organization.go create mode 100644 MCP/tools/actions/actions_set_allowed_actions_repository.go create mode 100644 MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_repo.go create mode 100644 MCP/tools/actions/actions_set_custom_oidc_sub_claim_for_repo.go create mode 100644 MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_organization.go create mode 100644 MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_repository.go create mode 100644 MCP/tools/actions/actions_set_github_actions_permissions_organization.go create mode 100644 MCP/tools/actions/actions_set_github_actions_permissions_repository.go create mode 100644 MCP/tools/actions/actions_set_repo_access_to_self_hosted_runner_group_in_org.go create mode 100644 MCP/tools/actions/actions_set_selected_repos_for_org_secret.go create mode 100644 MCP/tools/actions/actions_set_selected_repos_for_org_variable.go create mode 100644 MCP/tools/actions/actions_set_selected_repositories_enabled_github_actions_organization.go create mode 100644 MCP/tools/actions/actions_set_self_hosted_runners_in_group_for_org.go create mode 100644 MCP/tools/actions/actions_set_workflow_access_to_repository.go create mode 100644 MCP/tools/actions/actions_update_environment_variable.go create mode 100644 MCP/tools/actions/actions_update_hosted_runner_for_org.go create mode 100644 MCP/tools/actions/actions_update_org_variable.go create mode 100644 MCP/tools/actions/actions_update_repo_variable.go create mode 100644 MCP/tools/actions/actions_update_self_hosted_runner_group_for_org.go create mode 100644 MCP/tools/activity/activity_check_repo_is_starred_by_authenticated_user.go create mode 100644 MCP/tools/activity/activity_delete_repo_subscription.go create mode 100644 MCP/tools/activity/activity_delete_thread_subscription.go create mode 100644 MCP/tools/activity/activity_get_feeds.go create mode 100644 MCP/tools/activity/activity_get_repo_subscription.go create mode 100644 MCP/tools/activity/activity_get_thread.go create mode 100644 MCP/tools/activity/activity_get_thread_subscription_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_events_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_notifications_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_org_events_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_public_events.go create mode 100644 MCP/tools/activity/activity_list_public_events_for_repo_network.go create mode 100644 MCP/tools/activity/activity_list_public_events_for_user.go create mode 100644 MCP/tools/activity/activity_list_public_org_events.go create mode 100644 MCP/tools/activity/activity_list_received_events_for_user.go create mode 100644 MCP/tools/activity/activity_list_received_public_events_for_user.go create mode 100644 MCP/tools/activity/activity_list_repo_events.go create mode 100644 MCP/tools/activity/activity_list_repo_notifications_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_repos_starred_by_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_repos_starred_by_user.go create mode 100644 MCP/tools/activity/activity_list_repos_watched_by_user.go create mode 100644 MCP/tools/activity/activity_list_stargazers_for_repo.go create mode 100644 MCP/tools/activity/activity_list_watched_repos_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_list_watchers_for_repo.go create mode 100644 MCP/tools/activity/activity_mark_notifications_as_read.go create mode 100644 MCP/tools/activity/activity_mark_repo_notifications_as_read.go create mode 100644 MCP/tools/activity/activity_mark_thread_as_done.go create mode 100644 MCP/tools/activity/activity_mark_thread_as_read.go create mode 100644 MCP/tools/activity/activity_set_repo_subscription.go create mode 100644 MCP/tools/activity/activity_set_thread_subscription.go create mode 100644 MCP/tools/activity/activity_star_repo_for_authenticated_user.go create mode 100644 MCP/tools/activity/activity_unstar_repo_for_authenticated_user.go create mode 100644 MCP/tools/apps/apps_add_repo_to_installation_for_authenticated_user.go create mode 100644 MCP/tools/apps/apps_check_token.go create mode 100644 MCP/tools/apps/apps_create_from_manifest.go create mode 100644 MCP/tools/apps/apps_create_installation_access_token.go create mode 100644 MCP/tools/apps/apps_delete_authorization.go create mode 100644 MCP/tools/apps/apps_delete_installation.go create mode 100644 MCP/tools/apps/apps_delete_token.go create mode 100644 MCP/tools/apps/apps_get_authenticated.go create mode 100644 MCP/tools/apps/apps_get_by_slug.go create mode 100644 MCP/tools/apps/apps_get_installation.go create mode 100644 MCP/tools/apps/apps_get_org_installation.go create mode 100644 MCP/tools/apps/apps_get_repo_installation.go create mode 100644 MCP/tools/apps/apps_get_subscription_plan_for_account.go create mode 100644 MCP/tools/apps/apps_get_subscription_plan_for_account_stubbed.go create mode 100644 MCP/tools/apps/apps_get_user_installation.go create mode 100644 MCP/tools/apps/apps_get_webhook_config_for_app.go create mode 100644 MCP/tools/apps/apps_get_webhook_delivery.go create mode 100644 MCP/tools/apps/apps_list_accounts_for_plan.go create mode 100644 MCP/tools/apps/apps_list_accounts_for_plan_stubbed.go create mode 100644 MCP/tools/apps/apps_list_installation_repos_for_authenticated_user.go create mode 100644 MCP/tools/apps/apps_list_installation_requests_for_authenticated_app.go create mode 100644 MCP/tools/apps/apps_list_installations.go create mode 100644 MCP/tools/apps/apps_list_installations_for_authenticated_user.go create mode 100644 MCP/tools/apps/apps_list_plans.go create mode 100644 MCP/tools/apps/apps_list_plans_stubbed.go create mode 100644 MCP/tools/apps/apps_list_repos_accessible_to_installation.go create mode 100644 MCP/tools/apps/apps_list_subscriptions_for_authenticated_user.go create mode 100644 MCP/tools/apps/apps_list_subscriptions_for_authenticated_user_stubbed.go create mode 100644 MCP/tools/apps/apps_list_webhook_deliveries.go create mode 100644 MCP/tools/apps/apps_redeliver_webhook_delivery.go create mode 100644 MCP/tools/apps/apps_remove_repo_from_installation_for_authenticated_user.go create mode 100644 MCP/tools/apps/apps_reset_token.go create mode 100644 MCP/tools/apps/apps_revoke_installation_access_token.go create mode 100644 MCP/tools/apps/apps_scope_token.go create mode 100644 MCP/tools/apps/apps_suspend_installation.go create mode 100644 MCP/tools/apps/apps_unsuspend_installation.go create mode 100644 MCP/tools/apps/apps_update_webhook_config_for_app.go create mode 100644 MCP/tools/billing/billing_get_github_actions_billing_org.go create mode 100644 MCP/tools/billing/billing_get_github_actions_billing_user.go create mode 100644 MCP/tools/billing/billing_get_github_billing_usage_report_org.go create mode 100644 MCP/tools/billing/billing_get_github_billing_usage_report_user.go create mode 100644 MCP/tools/billing/billing_get_github_packages_billing_org.go create mode 100644 MCP/tools/billing/billing_get_github_packages_billing_user.go create mode 100644 MCP/tools/billing/billing_get_shared_storage_billing_org.go create mode 100644 MCP/tools/billing/billing_get_shared_storage_billing_user.go create mode 100644 MCP/tools/campaigns/campaigns_create_campaign.go create mode 100644 MCP/tools/campaigns/campaigns_delete_campaign.go create mode 100644 MCP/tools/campaigns/campaigns_get_campaign_summary.go create mode 100644 MCP/tools/campaigns/campaigns_list_org_campaigns.go create mode 100644 MCP/tools/campaigns/campaigns_update_campaign.go create mode 100644 MCP/tools/checks/checks_create.go create mode 100644 MCP/tools/checks/checks_create_suite.go create mode 100644 MCP/tools/checks/checks_get.go create mode 100644 MCP/tools/checks/checks_get_suite.go create mode 100644 MCP/tools/checks/checks_list_annotations.go create mode 100644 MCP/tools/checks/checks_list_for_ref.go create mode 100644 MCP/tools/checks/checks_list_for_suite.go create mode 100644 MCP/tools/checks/checks_list_suites_for_ref.go create mode 100644 MCP/tools/checks/checks_rerequest_run.go create mode 100644 MCP/tools/checks/checks_rerequest_suite.go create mode 100644 MCP/tools/checks/checks_set_suites_preferences.go create mode 100644 MCP/tools/checks/checks_update.go create mode 100644 MCP/tools/classroom/classroom_get_a_classroom.go create mode 100644 MCP/tools/classroom/classroom_get_an_assignment.go create mode 100644 MCP/tools/classroom/classroom_get_assignment_grades.go create mode 100644 MCP/tools/classroom/classroom_list_accepted_assignments_for_an_assignment.go create mode 100644 MCP/tools/classroom/classroom_list_assignments_for_a_classroom.go create mode 100644 MCP/tools/classroom/classroom_list_classrooms.go create mode 100644 MCP/tools/code_scanning/code_scanning_commit_autofix.go create mode 100644 MCP/tools/code_scanning/code_scanning_create_autofix.go create mode 100644 MCP/tools/code_scanning/code_scanning_create_variant_analysis.go create mode 100644 MCP/tools/code_scanning/code_scanning_delete_analysis.go create mode 100644 MCP/tools/code_scanning/code_scanning_delete_codeql_database.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_alert.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_analysis.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_autofix.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_codeql_database.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_default_setup.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_sarif.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_variant_analysis.go create mode 100644 MCP/tools/code_scanning/code_scanning_get_variant_analysis_repo_task.go create mode 100644 MCP/tools/code_scanning/code_scanning_list_alert_instances.go create mode 100644 MCP/tools/code_scanning/code_scanning_list_alerts_for_org.go create mode 100644 MCP/tools/code_scanning/code_scanning_list_alerts_for_repo.go create mode 100644 MCP/tools/code_scanning/code_scanning_list_codeql_databases.go create mode 100644 MCP/tools/code_scanning/code_scanning_list_recent_analyses.go create mode 100644 MCP/tools/code_scanning/code_scanning_update_alert.go create mode 100644 MCP/tools/code_scanning/code_scanning_update_default_setup.go create mode 100644 MCP/tools/code_scanning/code_scanning_upload_sarif.go create mode 100644 MCP/tools/code_security/code_security_attach_configuration.go create mode 100644 MCP/tools/code_security/code_security_attach_enterprise_configuration.go create mode 100644 MCP/tools/code_security/code_security_create_configuration.go create mode 100644 MCP/tools/code_security/code_security_create_configuration_for_enterprise.go create mode 100644 MCP/tools/code_security/code_security_delete_configuration.go create mode 100644 MCP/tools/code_security/code_security_delete_configuration_for_enterprise.go create mode 100644 MCP/tools/code_security/code_security_detach_configuration.go create mode 100644 MCP/tools/code_security/code_security_get_configuration.go create mode 100644 MCP/tools/code_security/code_security_get_configuration_for_repository.go create mode 100644 MCP/tools/code_security/code_security_get_configurations_for_enterprise.go create mode 100644 MCP/tools/code_security/code_security_get_configurations_for_org.go create mode 100644 MCP/tools/code_security/code_security_get_default_configurations.go create mode 100644 MCP/tools/code_security/code_security_get_default_configurations_for_enterprise.go create mode 100644 MCP/tools/code_security/code_security_get_repositories_for_configuration.go create mode 100644 MCP/tools/code_security/code_security_get_repositories_for_enterprise_configuration.go create mode 100644 MCP/tools/code_security/code_security_get_single_configuration_for_enterprise.go create mode 100644 MCP/tools/code_security/code_security_set_configuration_as_default.go create mode 100644 MCP/tools/code_security/code_security_set_configuration_as_default_for_enterprise.go create mode 100644 MCP/tools/code_security/code_security_update_configuration.go create mode 100644 MCP/tools/code_security/code_security_update_enterprise_configuration.go create mode 100644 MCP/tools/codes_of_conduct/codes_of_conduct_get_all_codes_of_conduct.go create mode 100644 MCP/tools/codes_of_conduct/codes_of_conduct_get_conduct_code.go create mode 100644 MCP/tools/codespaces/codespaces_add_repository_for_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_add_selected_repo_to_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_check_permissions_for_devcontainer.go create mode 100644 MCP/tools/codespaces/codespaces_codespace_machines_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_create_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_create_or_update_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_create_or_update_repo_secret.go create mode 100644 MCP/tools/codespaces/codespaces_create_or_update_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_create_with_pr_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_create_with_repo_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_delete_codespaces_access_users.go create mode 100644 MCP/tools/codespaces/codespaces_delete_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_delete_from_organization.go create mode 100644 MCP/tools/codespaces/codespaces_delete_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_delete_repo_secret.go create mode 100644 MCP/tools/codespaces/codespaces_delete_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_export_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_get_codespaces_for_user_in_org.go create mode 100644 MCP/tools/codespaces/codespaces_get_export_details_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_get_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_get_org_public_key.go create mode 100644 MCP/tools/codespaces/codespaces_get_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_get_public_key_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_get_repo_public_key.go create mode 100644 MCP/tools/codespaces/codespaces_get_repo_secret.go create mode 100644 MCP/tools/codespaces/codespaces_get_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_list_devcontainers_in_repository_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_list_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_list_in_organization.go create mode 100644 MCP/tools/codespaces/codespaces_list_in_repository_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_list_org_secrets.go create mode 100644 MCP/tools/codespaces/codespaces_list_repo_secrets.go create mode 100644 MCP/tools/codespaces/codespaces_list_repositories_for_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_list_secrets_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_list_selected_repos_for_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_pre_flight_with_repo_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_publish_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_remove_repository_for_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_remove_selected_repo_from_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_repo_machines_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_set_codespaces_access.go create mode 100644 MCP/tools/codespaces/codespaces_set_codespaces_access_users.go create mode 100644 MCP/tools/codespaces/codespaces_set_repositories_for_secret_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_set_selected_repos_for_org_secret.go create mode 100644 MCP/tools/codespaces/codespaces_start_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_stop_for_authenticated_user.go create mode 100644 MCP/tools/codespaces/codespaces_stop_in_organization.go create mode 100644 MCP/tools/codespaces/codespaces_update_for_authenticated_user.go create mode 100644 MCP/tools/copilot/copilot_add_copilot_seats_for_teams.go create mode 100644 MCP/tools/copilot/copilot_add_copilot_seats_for_users.go create mode 100644 MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_teams.go create mode 100644 MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_users.go create mode 100644 MCP/tools/copilot/copilot_copilot_metrics_for_organization.go create mode 100644 MCP/tools/copilot/copilot_copilot_metrics_for_team.go create mode 100644 MCP/tools/copilot/copilot_get_copilot_organization_details.go create mode 100644 MCP/tools/copilot/copilot_get_copilot_seat_details_for_user.go create mode 100644 MCP/tools/copilot/copilot_list_copilot_seats.go create mode 100644 MCP/tools/credentials/credentials_revoke.go create mode 100644 MCP/tools/dependabot/dependabot_add_selected_repo_to_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_create_or_update_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_create_or_update_repo_secret.go create mode 100644 MCP/tools/dependabot/dependabot_delete_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_delete_repo_secret.go create mode 100644 MCP/tools/dependabot/dependabot_get_alert.go create mode 100644 MCP/tools/dependabot/dependabot_get_org_public_key.go create mode 100644 MCP/tools/dependabot/dependabot_get_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_get_repo_public_key.go create mode 100644 MCP/tools/dependabot/dependabot_get_repo_secret.go create mode 100644 MCP/tools/dependabot/dependabot_list_alerts_for_enterprise.go create mode 100644 MCP/tools/dependabot/dependabot_list_alerts_for_org.go create mode 100644 MCP/tools/dependabot/dependabot_list_alerts_for_repo.go create mode 100644 MCP/tools/dependabot/dependabot_list_org_secrets.go create mode 100644 MCP/tools/dependabot/dependabot_list_repo_secrets.go create mode 100644 MCP/tools/dependabot/dependabot_list_selected_repos_for_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_remove_selected_repo_from_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_repository_access_for_org.go create mode 100644 MCP/tools/dependabot/dependabot_set_repository_access_default_level.go create mode 100644 MCP/tools/dependabot/dependabot_set_selected_repos_for_org_secret.go create mode 100644 MCP/tools/dependabot/dependabot_update_alert.go create mode 100644 MCP/tools/dependabot/dependabot_update_repository_access_for_org.go create mode 100644 MCP/tools/dependency_graph/dependency_graph_create_repository_snapshot.go create mode 100644 MCP/tools/dependency_graph/dependency_graph_diff_range.go create mode 100644 MCP/tools/dependency_graph/dependency_graph_export_sbom.go create mode 100644 MCP/tools/emojis/emojis_get.go create mode 100644 MCP/tools/gists/gists_check_is_starred.go create mode 100644 MCP/tools/gists/gists_create.go create mode 100644 MCP/tools/gists/gists_create_comment.go create mode 100644 MCP/tools/gists/gists_delete.go create mode 100644 MCP/tools/gists/gists_delete_comment.go create mode 100644 MCP/tools/gists/gists_fork.go create mode 100644 MCP/tools/gists/gists_get.go create mode 100644 MCP/tools/gists/gists_get_comment.go create mode 100644 MCP/tools/gists/gists_get_revision.go create mode 100644 MCP/tools/gists/gists_list.go create mode 100644 MCP/tools/gists/gists_list_comments.go create mode 100644 MCP/tools/gists/gists_list_commits.go create mode 100644 MCP/tools/gists/gists_list_for_user.go create mode 100644 MCP/tools/gists/gists_list_forks.go create mode 100644 MCP/tools/gists/gists_list_public.go create mode 100644 MCP/tools/gists/gists_list_starred.go create mode 100644 MCP/tools/gists/gists_star.go create mode 100644 MCP/tools/gists/gists_unstar.go create mode 100644 MCP/tools/gists/gists_update.go create mode 100644 MCP/tools/gists/gists_update_comment.go create mode 100644 MCP/tools/git/git_create_blob.go create mode 100644 MCP/tools/git/git_create_commit.go create mode 100644 MCP/tools/git/git_create_ref.go create mode 100644 MCP/tools/git/git_create_tag.go create mode 100644 MCP/tools/git/git_create_tree.go create mode 100644 MCP/tools/git/git_delete_ref.go create mode 100644 MCP/tools/git/git_get_blob.go create mode 100644 MCP/tools/git/git_get_commit.go create mode 100644 MCP/tools/git/git_get_ref.go create mode 100644 MCP/tools/git/git_get_tag.go create mode 100644 MCP/tools/git/git_get_tree.go create mode 100644 MCP/tools/git/git_list_matching_refs.go create mode 100644 MCP/tools/git/git_update_ref.go create mode 100644 MCP/tools/gitignore/gitignore_get_all_templates.go create mode 100644 MCP/tools/gitignore/gitignore_get_template.go create mode 100644 MCP/tools/hosted_compute/hosted_compute_create_network_configuration_for_org.go create mode 100644 MCP/tools/hosted_compute/hosted_compute_delete_network_configuration_from_org.go create mode 100644 MCP/tools/hosted_compute/hosted_compute_get_network_configuration_for_org.go create mode 100644 MCP/tools/hosted_compute/hosted_compute_get_network_settings_for_org.go create mode 100644 MCP/tools/hosted_compute/hosted_compute_list_network_configurations_for_org.go create mode 100644 MCP/tools/hosted_compute/hosted_compute_update_network_configuration_for_org.go create mode 100644 MCP/tools/interactions/interactions_get_restrictions_for_authenticated_user.go create mode 100644 MCP/tools/interactions/interactions_get_restrictions_for_org.go create mode 100644 MCP/tools/interactions/interactions_get_restrictions_for_repo.go create mode 100644 MCP/tools/interactions/interactions_remove_restrictions_for_authenticated_user.go create mode 100644 MCP/tools/interactions/interactions_remove_restrictions_for_org.go create mode 100644 MCP/tools/interactions/interactions_remove_restrictions_for_repo.go create mode 100644 MCP/tools/interactions/interactions_set_restrictions_for_authenticated_user.go create mode 100644 MCP/tools/interactions/interactions_set_restrictions_for_org.go create mode 100644 MCP/tools/interactions/interactions_set_restrictions_for_repo.go create mode 100644 MCP/tools/issues/issues_add_assignees.go create mode 100644 MCP/tools/issues/issues_add_labels.go create mode 100644 MCP/tools/issues/issues_add_sub_issue.go create mode 100644 MCP/tools/issues/issues_check_user_can_be_assigned.go create mode 100644 MCP/tools/issues/issues_check_user_can_be_assigned_to_issue.go create mode 100644 MCP/tools/issues/issues_create.go create mode 100644 MCP/tools/issues/issues_create_comment.go create mode 100644 MCP/tools/issues/issues_create_label.go create mode 100644 MCP/tools/issues/issues_create_milestone.go create mode 100644 MCP/tools/issues/issues_delete_comment.go create mode 100644 MCP/tools/issues/issues_delete_label.go create mode 100644 MCP/tools/issues/issues_delete_milestone.go create mode 100644 MCP/tools/issues/issues_get.go create mode 100644 MCP/tools/issues/issues_get_comment.go create mode 100644 MCP/tools/issues/issues_get_event.go create mode 100644 MCP/tools/issues/issues_get_label.go create mode 100644 MCP/tools/issues/issues_get_milestone.go create mode 100644 MCP/tools/issues/issues_list.go create mode 100644 MCP/tools/issues/issues_list_assignees.go create mode 100644 MCP/tools/issues/issues_list_comments.go create mode 100644 MCP/tools/issues/issues_list_comments_for_repo.go create mode 100644 MCP/tools/issues/issues_list_events.go create mode 100644 MCP/tools/issues/issues_list_events_for_repo.go create mode 100644 MCP/tools/issues/issues_list_events_for_timeline.go create mode 100644 MCP/tools/issues/issues_list_for_authenticated_user.go create mode 100644 MCP/tools/issues/issues_list_for_org.go create mode 100644 MCP/tools/issues/issues_list_for_repo.go create mode 100644 MCP/tools/issues/issues_list_labels_for_milestone.go create mode 100644 MCP/tools/issues/issues_list_labels_for_repo.go create mode 100644 MCP/tools/issues/issues_list_labels_on_issue.go create mode 100644 MCP/tools/issues/issues_list_milestones.go create mode 100644 MCP/tools/issues/issues_list_sub_issues.go create mode 100644 MCP/tools/issues/issues_lock.go create mode 100644 MCP/tools/issues/issues_remove_all_labels.go create mode 100644 MCP/tools/issues/issues_remove_assignees.go create mode 100644 MCP/tools/issues/issues_remove_label.go create mode 100644 MCP/tools/issues/issues_remove_sub_issue.go create mode 100644 MCP/tools/issues/issues_reprioritize_sub_issue.go create mode 100644 MCP/tools/issues/issues_set_labels.go create mode 100644 MCP/tools/issues/issues_unlock.go create mode 100644 MCP/tools/issues/issues_update.go create mode 100644 MCP/tools/issues/issues_update_comment.go create mode 100644 MCP/tools/issues/issues_update_label.go create mode 100644 MCP/tools/issues/issues_update_milestone.go create mode 100644 MCP/tools/licenses/licenses_get.go create mode 100644 MCP/tools/licenses/licenses_get_all_commonly_used.go create mode 100644 MCP/tools/licenses/licenses_get_for_repo.go create mode 100644 MCP/tools/meta/meta_get.go create mode 100644 MCP/tools/meta/meta_get_all_versions.go create mode 100644 MCP/tools/meta/meta_get_zen.go create mode 100644 MCP/tools/meta/meta_root.go create mode 100644 MCP/tools/migrations/migrations_cancel_import.go create mode 100644 MCP/tools/migrations/migrations_delete_archive_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_delete_archive_for_org.go create mode 100644 MCP/tools/migrations/migrations_download_archive_for_org.go create mode 100644 MCP/tools/migrations/migrations_get_archive_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_get_commit_authors.go create mode 100644 MCP/tools/migrations/migrations_get_import_status.go create mode 100644 MCP/tools/migrations/migrations_get_large_files.go create mode 100644 MCP/tools/migrations/migrations_get_status_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_get_status_for_org.go create mode 100644 MCP/tools/migrations/migrations_list_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_list_for_org.go create mode 100644 MCP/tools/migrations/migrations_list_repos_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_list_repos_for_org.go create mode 100644 MCP/tools/migrations/migrations_map_commit_author.go create mode 100644 MCP/tools/migrations/migrations_set_lfs_preference.go create mode 100644 MCP/tools/migrations/migrations_start_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_start_for_org.go create mode 100644 MCP/tools/migrations/migrations_start_import.go create mode 100644 MCP/tools/migrations/migrations_unlock_repo_for_authenticated_user.go create mode 100644 MCP/tools/migrations/migrations_unlock_repo_for_org.go create mode 100644 MCP/tools/migrations/migrations_update_import.go create mode 100644 MCP/tools/oidc/oidc_get_oidc_custom_sub_template_for_org.go create mode 100644 MCP/tools/oidc/oidc_update_oidc_custom_sub_template_for_org.go create mode 100644 MCP/tools/orgs/api_insights_get_route_stats_by_actor.go create mode 100644 MCP/tools/orgs/api_insights_get_subject_stats.go create mode 100644 MCP/tools/orgs/api_insights_get_summary_stats.go create mode 100644 MCP/tools/orgs/api_insights_get_summary_stats_by_actor.go create mode 100644 MCP/tools/orgs/api_insights_get_summary_stats_by_user.go create mode 100644 MCP/tools/orgs/api_insights_get_time_stats.go create mode 100644 MCP/tools/orgs/api_insights_get_time_stats_by_actor.go create mode 100644 MCP/tools/orgs/api_insights_get_time_stats_by_user.go create mode 100644 MCP/tools/orgs/api_insights_get_user_stats.go create mode 100644 MCP/tools/orgs/orgs_add_security_manager_team.go create mode 100644 MCP/tools/orgs/orgs_assign_team_to_org_role.go create mode 100644 MCP/tools/orgs/orgs_assign_user_to_org_role.go create mode 100644 MCP/tools/orgs/orgs_block_user.go create mode 100644 MCP/tools/orgs/orgs_cancel_invitation.go create mode 100644 MCP/tools/orgs/orgs_check_blocked_user.go create mode 100644 MCP/tools/orgs/orgs_check_membership_for_user.go create mode 100644 MCP/tools/orgs/orgs_check_public_membership_for_user.go create mode 100644 MCP/tools/orgs/orgs_convert_member_to_outside_collaborator.go create mode 100644 MCP/tools/orgs/orgs_create_invitation.go create mode 100644 MCP/tools/orgs/orgs_create_issue_type.go create mode 100644 MCP/tools/orgs/orgs_create_or_update_custom_properties.go create mode 100644 MCP/tools/orgs/orgs_create_or_update_custom_properties_values_for_repos.go create mode 100644 MCP/tools/orgs/orgs_create_or_update_custom_property.go create mode 100644 MCP/tools/orgs/orgs_create_webhook.go create mode 100644 MCP/tools/orgs/orgs_delete.go create mode 100644 MCP/tools/orgs/orgs_delete_attestations_bulk.go create mode 100644 MCP/tools/orgs/orgs_delete_attestations_by_id.go create mode 100644 MCP/tools/orgs/orgs_delete_attestations_by_subject_digest.go create mode 100644 MCP/tools/orgs/orgs_delete_issue_type.go create mode 100644 MCP/tools/orgs/orgs_delete_webhook.go create mode 100644 MCP/tools/orgs/orgs_enable_or_disable_security_product_on_all_org_repos.go create mode 100644 MCP/tools/orgs/orgs_get.go create mode 100644 MCP/tools/orgs/orgs_get_all_custom_properties.go create mode 100644 MCP/tools/orgs/orgs_get_custom_property.go create mode 100644 MCP/tools/orgs/orgs_get_membership_for_authenticated_user.go create mode 100644 MCP/tools/orgs/orgs_get_membership_for_user.go create mode 100644 MCP/tools/orgs/orgs_get_org_role.go create mode 100644 MCP/tools/orgs/orgs_get_org_ruleset_history.go create mode 100644 MCP/tools/orgs/orgs_get_org_ruleset_version.go create mode 100644 MCP/tools/orgs/orgs_get_webhook.go create mode 100644 MCP/tools/orgs/orgs_get_webhook_config_for_org.go create mode 100644 MCP/tools/orgs/orgs_get_webhook_delivery.go create mode 100644 MCP/tools/orgs/orgs_list.go create mode 100644 MCP/tools/orgs/orgs_list_app_installations.go create mode 100644 MCP/tools/orgs/orgs_list_attestations.go create mode 100644 MCP/tools/orgs/orgs_list_attestations_bulk.go create mode 100644 MCP/tools/orgs/orgs_list_blocked_users.go create mode 100644 MCP/tools/orgs/orgs_list_custom_properties_values_for_repos.go create mode 100644 MCP/tools/orgs/orgs_list_failed_invitations.go create mode 100644 MCP/tools/orgs/orgs_list_for_authenticated_user.go create mode 100644 MCP/tools/orgs/orgs_list_for_user.go create mode 100644 MCP/tools/orgs/orgs_list_invitation_teams.go create mode 100644 MCP/tools/orgs/orgs_list_issue_types.go create mode 100644 MCP/tools/orgs/orgs_list_members.go create mode 100644 MCP/tools/orgs/orgs_list_memberships_for_authenticated_user.go create mode 100644 MCP/tools/orgs/orgs_list_org_role_teams.go create mode 100644 MCP/tools/orgs/orgs_list_org_role_users.go create mode 100644 MCP/tools/orgs/orgs_list_org_roles.go create mode 100644 MCP/tools/orgs/orgs_list_outside_collaborators.go create mode 100644 MCP/tools/orgs/orgs_list_pat_grant_repositories.go create mode 100644 MCP/tools/orgs/orgs_list_pat_grant_request_repositories.go create mode 100644 MCP/tools/orgs/orgs_list_pat_grant_requests.go create mode 100644 MCP/tools/orgs/orgs_list_pat_grants.go create mode 100644 MCP/tools/orgs/orgs_list_pending_invitations.go create mode 100644 MCP/tools/orgs/orgs_list_public_members.go create mode 100644 MCP/tools/orgs/orgs_list_security_manager_teams.go create mode 100644 MCP/tools/orgs/orgs_list_webhook_deliveries.go create mode 100644 MCP/tools/orgs/orgs_list_webhooks.go create mode 100644 MCP/tools/orgs/orgs_ping_webhook.go create mode 100644 MCP/tools/orgs/orgs_redeliver_webhook_delivery.go create mode 100644 MCP/tools/orgs/orgs_remove_custom_property.go create mode 100644 MCP/tools/orgs/orgs_remove_member.go create mode 100644 MCP/tools/orgs/orgs_remove_membership_for_user.go create mode 100644 MCP/tools/orgs/orgs_remove_outside_collaborator.go create mode 100644 MCP/tools/orgs/orgs_remove_public_membership_for_authenticated_user.go create mode 100644 MCP/tools/orgs/orgs_remove_security_manager_team.go create mode 100644 MCP/tools/orgs/orgs_review_pat_grant_request.go create mode 100644 MCP/tools/orgs/orgs_review_pat_grant_requests_in_bulk.go create mode 100644 MCP/tools/orgs/orgs_revoke_all_org_roles_team.go create mode 100644 MCP/tools/orgs/orgs_revoke_all_org_roles_user.go create mode 100644 MCP/tools/orgs/orgs_revoke_org_role_team.go create mode 100644 MCP/tools/orgs/orgs_revoke_org_role_user.go create mode 100644 MCP/tools/orgs/orgs_set_membership_for_user.go create mode 100644 MCP/tools/orgs/orgs_set_public_membership_for_authenticated_user.go create mode 100644 MCP/tools/orgs/orgs_unblock_user.go create mode 100644 MCP/tools/orgs/orgs_update.go create mode 100644 MCP/tools/orgs/orgs_update_issue_type.go create mode 100644 MCP/tools/orgs/orgs_update_membership_for_authenticated_user.go create mode 100644 MCP/tools/orgs/orgs_update_pat_access.go create mode 100644 MCP/tools/orgs/orgs_update_pat_accesses.go create mode 100644 MCP/tools/orgs/orgs_update_webhook.go create mode 100644 MCP/tools/orgs/orgs_update_webhook_config_for_org.go create mode 100644 MCP/tools/packages/packages_delete_package_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_delete_package_for_org.go create mode 100644 MCP/tools/packages/packages_delete_package_for_user.go create mode 100644 MCP/tools/packages/packages_delete_package_version_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_delete_package_version_for_org.go create mode 100644 MCP/tools/packages/packages_delete_package_version_for_user.go create mode 100644 MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_authenticated_user.go create mode 100644 MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_org.go create mode 100644 MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_user.go create mode 100644 MCP/tools/packages/packages_get_package_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_get_package_for_organization.go create mode 100644 MCP/tools/packages/packages_get_package_for_user.go create mode 100644 MCP/tools/packages/packages_get_package_version_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_get_package_version_for_organization.go create mode 100644 MCP/tools/packages/packages_get_package_version_for_user.go create mode 100644 MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_organization.go create mode 100644 MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_user.go create mode 100644 MCP/tools/packages/packages_list_packages_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_list_packages_for_organization.go create mode 100644 MCP/tools/packages/packages_list_packages_for_user.go create mode 100644 MCP/tools/packages/packages_restore_package_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_restore_package_for_org.go create mode 100644 MCP/tools/packages/packages_restore_package_for_user.go create mode 100644 MCP/tools/packages/packages_restore_package_version_for_authenticated_user.go create mode 100644 MCP/tools/packages/packages_restore_package_version_for_org.go create mode 100644 MCP/tools/packages/packages_restore_package_version_for_user.go create mode 100644 MCP/tools/private_registries/private_registries_create_org_private_registry.go create mode 100644 MCP/tools/private_registries/private_registries_delete_org_private_registry.go create mode 100644 MCP/tools/private_registries/private_registries_get_org_private_registry.go create mode 100644 MCP/tools/private_registries/private_registries_get_org_public_key.go create mode 100644 MCP/tools/private_registries/private_registries_list_org_private_registries.go create mode 100644 MCP/tools/private_registries/private_registries_update_org_private_registry.go create mode 100644 MCP/tools/projects/projects_add_collaborator.go create mode 100644 MCP/tools/projects/projects_create_card.go create mode 100644 MCP/tools/projects/projects_create_column.go create mode 100644 MCP/tools/projects/projects_create_for_authenticated_user.go create mode 100644 MCP/tools/projects/projects_create_for_org.go create mode 100644 MCP/tools/projects/projects_create_for_repo.go create mode 100644 MCP/tools/projects/projects_delete.go create mode 100644 MCP/tools/projects/projects_delete_card.go create mode 100644 MCP/tools/projects/projects_delete_column.go create mode 100644 MCP/tools/projects/projects_get.go create mode 100644 MCP/tools/projects/projects_get_card.go create mode 100644 MCP/tools/projects/projects_get_column.go create mode 100644 MCP/tools/projects/projects_get_permission_for_user.go create mode 100644 MCP/tools/projects/projects_list_cards.go create mode 100644 MCP/tools/projects/projects_list_collaborators.go create mode 100644 MCP/tools/projects/projects_list_columns.go create mode 100644 MCP/tools/projects/projects_list_for_org.go create mode 100644 MCP/tools/projects/projects_list_for_repo.go create mode 100644 MCP/tools/projects/projects_list_for_user.go create mode 100644 MCP/tools/projects/projects_move_card.go create mode 100644 MCP/tools/projects/projects_move_column.go create mode 100644 MCP/tools/projects/projects_remove_collaborator.go create mode 100644 MCP/tools/projects/projects_update.go create mode 100644 MCP/tools/projects/projects_update_card.go create mode 100644 MCP/tools/projects/projects_update_column.go create mode 100644 MCP/tools/pulls/pulls_check_if_merged.go create mode 100644 MCP/tools/pulls/pulls_create.go create mode 100644 MCP/tools/pulls/pulls_create_reply_for_review_comment.go create mode 100644 MCP/tools/pulls/pulls_create_review.go create mode 100644 MCP/tools/pulls/pulls_create_review_comment.go create mode 100644 MCP/tools/pulls/pulls_delete_pending_review.go create mode 100644 MCP/tools/pulls/pulls_delete_review_comment.go create mode 100644 MCP/tools/pulls/pulls_dismiss_review.go create mode 100644 MCP/tools/pulls/pulls_get.go create mode 100644 MCP/tools/pulls/pulls_get_review.go create mode 100644 MCP/tools/pulls/pulls_get_review_comment.go create mode 100644 MCP/tools/pulls/pulls_list.go create mode 100644 MCP/tools/pulls/pulls_list_comments_for_review.go create mode 100644 MCP/tools/pulls/pulls_list_commits.go create mode 100644 MCP/tools/pulls/pulls_list_files.go create mode 100644 MCP/tools/pulls/pulls_list_requested_reviewers.go create mode 100644 MCP/tools/pulls/pulls_list_review_comments.go create mode 100644 MCP/tools/pulls/pulls_list_review_comments_for_repo.go create mode 100644 MCP/tools/pulls/pulls_list_reviews.go create mode 100644 MCP/tools/pulls/pulls_merge.go create mode 100644 MCP/tools/pulls/pulls_remove_requested_reviewers.go create mode 100644 MCP/tools/pulls/pulls_request_reviewers.go create mode 100644 MCP/tools/pulls/pulls_submit_review.go create mode 100644 MCP/tools/pulls/pulls_update.go create mode 100644 MCP/tools/pulls/pulls_update_branch.go create mode 100644 MCP/tools/pulls/pulls_update_review.go create mode 100644 MCP/tools/pulls/pulls_update_review_comment.go create mode 100644 MCP/tools/rate_limit/rate_limit_get.go create mode 100644 MCP/tools/reactions/reactions_create_for_commit_comment.go create mode 100644 MCP/tools/reactions/reactions_create_for_issue.go create mode 100644 MCP/tools/reactions/reactions_create_for_issue_comment.go create mode 100644 MCP/tools/reactions/reactions_create_for_pull_request_review_comment.go create mode 100644 MCP/tools/reactions/reactions_create_for_release.go create mode 100644 MCP/tools/reactions/reactions_create_for_team_discussion_comment_in_org.go create mode 100644 MCP/tools/reactions/reactions_create_for_team_discussion_comment_legacy.go create mode 100644 MCP/tools/reactions/reactions_create_for_team_discussion_in_org.go create mode 100644 MCP/tools/reactions/reactions_create_for_team_discussion_legacy.go create mode 100644 MCP/tools/reactions/reactions_delete_for_commit_comment.go create mode 100644 MCP/tools/reactions/reactions_delete_for_issue.go create mode 100644 MCP/tools/reactions/reactions_delete_for_issue_comment.go create mode 100644 MCP/tools/reactions/reactions_delete_for_pull_request_comment.go create mode 100644 MCP/tools/reactions/reactions_delete_for_release.go create mode 100644 MCP/tools/reactions/reactions_delete_for_team_discussion.go create mode 100644 MCP/tools/reactions/reactions_delete_for_team_discussion_comment.go create mode 100644 MCP/tools/reactions/reactions_list_for_commit_comment.go create mode 100644 MCP/tools/reactions/reactions_list_for_issue.go create mode 100644 MCP/tools/reactions/reactions_list_for_issue_comment.go create mode 100644 MCP/tools/reactions/reactions_list_for_pull_request_review_comment.go create mode 100644 MCP/tools/reactions/reactions_list_for_release.go create mode 100644 MCP/tools/reactions/reactions_list_for_team_discussion_comment_in_org.go create mode 100644 MCP/tools/reactions/reactions_list_for_team_discussion_comment_legacy.go create mode 100644 MCP/tools/reactions/reactions_list_for_team_discussion_in_org.go create mode 100644 MCP/tools/reactions/reactions_list_for_team_discussion_legacy.go create mode 100644 MCP/tools/repos/repos_accept_invitation_for_authenticated_user.go create mode 100644 MCP/tools/repos/repos_add_app_access_restrictions.go create mode 100644 MCP/tools/repos/repos_add_collaborator.go create mode 100644 MCP/tools/repos/repos_add_status_check_contexts.go create mode 100644 MCP/tools/repos/repos_add_team_access_restrictions.go create mode 100644 MCP/tools/repos/repos_add_user_access_restrictions.go create mode 100644 MCP/tools/repos/repos_cancel_pages_deployment.go create mode 100644 MCP/tools/repos/repos_check_automated_security_fixes.go create mode 100644 MCP/tools/repos/repos_check_collaborator.go create mode 100644 MCP/tools/repos/repos_check_private_vulnerability_reporting.go create mode 100644 MCP/tools/repos/repos_check_vulnerability_alerts.go create mode 100644 MCP/tools/repos/repos_codeowners_errors.go create mode 100644 MCP/tools/repos/repos_compare_commits.go create mode 100644 MCP/tools/repos/repos_create_attestation.go create mode 100644 MCP/tools/repos/repos_create_autolink.go create mode 100644 MCP/tools/repos/repos_create_commit_comment.go create mode 100644 MCP/tools/repos/repos_create_commit_signature_protection.go create mode 100644 MCP/tools/repos/repos_create_commit_status.go create mode 100644 MCP/tools/repos/repos_create_deploy_key.go create mode 100644 MCP/tools/repos/repos_create_deployment.go create mode 100644 MCP/tools/repos/repos_create_deployment_branch_policy.go create mode 100644 MCP/tools/repos/repos_create_deployment_protection_rule.go create mode 100644 MCP/tools/repos/repos_create_deployment_status.go create mode 100644 MCP/tools/repos/repos_create_dispatch_event.go create mode 100644 MCP/tools/repos/repos_create_for_authenticated_user.go create mode 100644 MCP/tools/repos/repos_create_fork.go create mode 100644 MCP/tools/repos/repos_create_in_org.go create mode 100644 MCP/tools/repos/repos_create_or_update_custom_properties_values.go create mode 100644 MCP/tools/repos/repos_create_or_update_environment.go create mode 100644 MCP/tools/repos/repos_create_or_update_file_contents.go create mode 100644 MCP/tools/repos/repos_create_org_ruleset.go create mode 100644 MCP/tools/repos/repos_create_pages_deployment.go create mode 100644 MCP/tools/repos/repos_create_pages_site.go create mode 100644 MCP/tools/repos/repos_create_release.go create mode 100644 MCP/tools/repos/repos_create_repo_ruleset.go create mode 100644 MCP/tools/repos/repos_create_tag_protection.go create mode 100644 MCP/tools/repos/repos_create_using_template.go create mode 100644 MCP/tools/repos/repos_create_webhook.go create mode 100644 MCP/tools/repos/repos_decline_invitation_for_authenticated_user.go create mode 100644 MCP/tools/repos/repos_delete.go create mode 100644 MCP/tools/repos/repos_delete_access_restrictions.go create mode 100644 MCP/tools/repos/repos_delete_admin_branch_protection.go create mode 100644 MCP/tools/repos/repos_delete_an_environment.go create mode 100644 MCP/tools/repos/repos_delete_autolink.go create mode 100644 MCP/tools/repos/repos_delete_branch_protection.go create mode 100644 MCP/tools/repos/repos_delete_commit_comment.go create mode 100644 MCP/tools/repos/repos_delete_commit_signature_protection.go create mode 100644 MCP/tools/repos/repos_delete_deploy_key.go create mode 100644 MCP/tools/repos/repos_delete_deployment.go create mode 100644 MCP/tools/repos/repos_delete_deployment_branch_policy.go create mode 100644 MCP/tools/repos/repos_delete_file.go create mode 100644 MCP/tools/repos/repos_delete_invitation.go create mode 100644 MCP/tools/repos/repos_delete_org_ruleset.go create mode 100644 MCP/tools/repos/repos_delete_pages_site.go create mode 100644 MCP/tools/repos/repos_delete_pull_request_review_protection.go create mode 100644 MCP/tools/repos/repos_delete_release.go create mode 100644 MCP/tools/repos/repos_delete_release_asset.go create mode 100644 MCP/tools/repos/repos_delete_repo_ruleset.go create mode 100644 MCP/tools/repos/repos_delete_tag_protection.go create mode 100644 MCP/tools/repos/repos_delete_webhook.go create mode 100644 MCP/tools/repos/repos_disable_automated_security_fixes.go create mode 100644 MCP/tools/repos/repos_disable_deployment_protection_rule.go create mode 100644 MCP/tools/repos/repos_disable_private_vulnerability_reporting.go create mode 100644 MCP/tools/repos/repos_disable_vulnerability_alerts.go create mode 100644 MCP/tools/repos/repos_download_tarball_archive.go create mode 100644 MCP/tools/repos/repos_download_zipball_archive.go create mode 100644 MCP/tools/repos/repos_enable_automated_security_fixes.go create mode 100644 MCP/tools/repos/repos_enable_private_vulnerability_reporting.go create mode 100644 MCP/tools/repos/repos_enable_vulnerability_alerts.go create mode 100644 MCP/tools/repos/repos_generate_release_notes.go create mode 100644 MCP/tools/repos/repos_get.go create mode 100644 MCP/tools/repos/repos_get_access_restrictions.go create mode 100644 MCP/tools/repos/repos_get_admin_branch_protection.go create mode 100644 MCP/tools/repos/repos_get_all_deployment_protection_rules.go create mode 100644 MCP/tools/repos/repos_get_all_environments.go create mode 100644 MCP/tools/repos/repos_get_all_status_check_contexts.go create mode 100644 MCP/tools/repos/repos_get_all_topics.go create mode 100644 MCP/tools/repos/repos_get_apps_with_access_to_protected_branch.go create mode 100644 MCP/tools/repos/repos_get_autolink.go create mode 100644 MCP/tools/repos/repos_get_branch.go create mode 100644 MCP/tools/repos/repos_get_branch_protection.go create mode 100644 MCP/tools/repos/repos_get_branch_rules.go create mode 100644 MCP/tools/repos/repos_get_clones.go create mode 100644 MCP/tools/repos/repos_get_code_frequency_stats.go create mode 100644 MCP/tools/repos/repos_get_collaborator_permission_level.go create mode 100644 MCP/tools/repos/repos_get_combined_status_for_ref.go create mode 100644 MCP/tools/repos/repos_get_commit.go create mode 100644 MCP/tools/repos/repos_get_commit_activity_stats.go create mode 100644 MCP/tools/repos/repos_get_commit_comment.go create mode 100644 MCP/tools/repos/repos_get_commit_signature_protection.go create mode 100644 MCP/tools/repos/repos_get_community_profile_metrics.go create mode 100644 MCP/tools/repos/repos_get_content.go create mode 100644 MCP/tools/repos/repos_get_contributors_stats.go create mode 100644 MCP/tools/repos/repos_get_custom_deployment_protection_rule.go create mode 100644 MCP/tools/repos/repos_get_custom_properties_values.go create mode 100644 MCP/tools/repos/repos_get_deploy_key.go create mode 100644 MCP/tools/repos/repos_get_deployment.go create mode 100644 MCP/tools/repos/repos_get_deployment_branch_policy.go create mode 100644 MCP/tools/repos/repos_get_deployment_status.go create mode 100644 MCP/tools/repos/repos_get_environment.go create mode 100644 MCP/tools/repos/repos_get_latest_pages_build.go create mode 100644 MCP/tools/repos/repos_get_latest_release.go create mode 100644 MCP/tools/repos/repos_get_org_rule_suite.go create mode 100644 MCP/tools/repos/repos_get_org_rule_suites.go create mode 100644 MCP/tools/repos/repos_get_org_ruleset.go create mode 100644 MCP/tools/repos/repos_get_org_rulesets.go create mode 100644 MCP/tools/repos/repos_get_pages.go create mode 100644 MCP/tools/repos/repos_get_pages_build.go create mode 100644 MCP/tools/repos/repos_get_pages_deployment.go create mode 100644 MCP/tools/repos/repos_get_pages_health_check.go create mode 100644 MCP/tools/repos/repos_get_participation_stats.go create mode 100644 MCP/tools/repos/repos_get_pull_request_review_protection.go create mode 100644 MCP/tools/repos/repos_get_punch_card_stats.go create mode 100644 MCP/tools/repos/repos_get_readme.go create mode 100644 MCP/tools/repos/repos_get_readme_in_directory.go create mode 100644 MCP/tools/repos/repos_get_release.go create mode 100644 MCP/tools/repos/repos_get_release_asset.go create mode 100644 MCP/tools/repos/repos_get_release_by_tag.go create mode 100644 MCP/tools/repos/repos_get_repo_rule_suite.go create mode 100644 MCP/tools/repos/repos_get_repo_rule_suites.go create mode 100644 MCP/tools/repos/repos_get_repo_ruleset.go create mode 100644 MCP/tools/repos/repos_get_repo_ruleset_history.go create mode 100644 MCP/tools/repos/repos_get_repo_ruleset_version.go create mode 100644 MCP/tools/repos/repos_get_repo_rulesets.go create mode 100644 MCP/tools/repos/repos_get_status_checks_protection.go create mode 100644 MCP/tools/repos/repos_get_teams_with_access_to_protected_branch.go create mode 100644 MCP/tools/repos/repos_get_top_paths.go create mode 100644 MCP/tools/repos/repos_get_top_referrers.go create mode 100644 MCP/tools/repos/repos_get_users_with_access_to_protected_branch.go create mode 100644 MCP/tools/repos/repos_get_views.go create mode 100644 MCP/tools/repos/repos_get_webhook.go create mode 100644 MCP/tools/repos/repos_get_webhook_config_for_repo.go create mode 100644 MCP/tools/repos/repos_get_webhook_delivery.go create mode 100644 MCP/tools/repos/repos_list_activities.go create mode 100644 MCP/tools/repos/repos_list_attestations.go create mode 100644 MCP/tools/repos/repos_list_autolinks.go create mode 100644 MCP/tools/repos/repos_list_branches.go create mode 100644 MCP/tools/repos/repos_list_branches_for_head_commit.go create mode 100644 MCP/tools/repos/repos_list_collaborators.go create mode 100644 MCP/tools/repos/repos_list_comments_for_commit.go create mode 100644 MCP/tools/repos/repos_list_commit_comments_for_repo.go create mode 100644 MCP/tools/repos/repos_list_commit_statuses_for_ref.go create mode 100644 MCP/tools/repos/repos_list_commits.go create mode 100644 MCP/tools/repos/repos_list_contributors.go create mode 100644 MCP/tools/repos/repos_list_custom_deployment_rule_integrations.go create mode 100644 MCP/tools/repos/repos_list_deploy_keys.go create mode 100644 MCP/tools/repos/repos_list_deployment_branch_policies.go create mode 100644 MCP/tools/repos/repos_list_deployment_statuses.go create mode 100644 MCP/tools/repos/repos_list_deployments.go create mode 100644 MCP/tools/repos/repos_list_for_authenticated_user.go create mode 100644 MCP/tools/repos/repos_list_for_org.go create mode 100644 MCP/tools/repos/repos_list_for_user.go create mode 100644 MCP/tools/repos/repos_list_forks.go create mode 100644 MCP/tools/repos/repos_list_invitations.go create mode 100644 MCP/tools/repos/repos_list_invitations_for_authenticated_user.go create mode 100644 MCP/tools/repos/repos_list_languages.go create mode 100644 MCP/tools/repos/repos_list_pages_builds.go create mode 100644 MCP/tools/repos/repos_list_public.go create mode 100644 MCP/tools/repos/repos_list_pull_requests_associated_with_commit.go create mode 100644 MCP/tools/repos/repos_list_release_assets.go create mode 100644 MCP/tools/repos/repos_list_releases.go create mode 100644 MCP/tools/repos/repos_list_tag_protection.go create mode 100644 MCP/tools/repos/repos_list_tags.go create mode 100644 MCP/tools/repos/repos_list_teams.go create mode 100644 MCP/tools/repos/repos_list_webhook_deliveries.go create mode 100644 MCP/tools/repos/repos_list_webhooks.go create mode 100644 MCP/tools/repos/repos_merge.go create mode 100644 MCP/tools/repos/repos_merge_upstream.go create mode 100644 MCP/tools/repos/repos_ping_webhook.go create mode 100644 MCP/tools/repos/repos_redeliver_webhook_delivery.go create mode 100644 MCP/tools/repos/repos_remove_app_access_restrictions.go create mode 100644 MCP/tools/repos/repos_remove_collaborator.go create mode 100644 MCP/tools/repos/repos_remove_status_check_contexts.go create mode 100644 MCP/tools/repos/repos_remove_status_check_protection.go create mode 100644 MCP/tools/repos/repos_remove_team_access_restrictions.go create mode 100644 MCP/tools/repos/repos_remove_user_access_restrictions.go create mode 100644 MCP/tools/repos/repos_rename_branch.go create mode 100644 MCP/tools/repos/repos_replace_all_topics.go create mode 100644 MCP/tools/repos/repos_request_pages_build.go create mode 100644 MCP/tools/repos/repos_set_admin_branch_protection.go create mode 100644 MCP/tools/repos/repos_set_app_access_restrictions.go create mode 100644 MCP/tools/repos/repos_set_status_check_contexts.go create mode 100644 MCP/tools/repos/repos_set_team_access_restrictions.go create mode 100644 MCP/tools/repos/repos_set_user_access_restrictions.go create mode 100644 MCP/tools/repos/repos_test_push_webhook.go create mode 100644 MCP/tools/repos/repos_transfer.go create mode 100644 MCP/tools/repos/repos_update.go create mode 100644 MCP/tools/repos/repos_update_branch_protection.go create mode 100644 MCP/tools/repos/repos_update_commit_comment.go create mode 100644 MCP/tools/repos/repos_update_deployment_branch_policy.go create mode 100644 MCP/tools/repos/repos_update_information_about_pages_site.go create mode 100644 MCP/tools/repos/repos_update_invitation.go create mode 100644 MCP/tools/repos/repos_update_org_ruleset.go create mode 100644 MCP/tools/repos/repos_update_pull_request_review_protection.go create mode 100644 MCP/tools/repos/repos_update_release.go create mode 100644 MCP/tools/repos/repos_update_release_asset.go create mode 100644 MCP/tools/repos/repos_update_repo_ruleset.go create mode 100644 MCP/tools/repos/repos_update_status_check_protection.go create mode 100644 MCP/tools/repos/repos_update_webhook.go create mode 100644 MCP/tools/repos/repos_update_webhook_config_for_repo.go create mode 100644 MCP/tools/search/search_code.go create mode 100644 MCP/tools/search/search_commits.go create mode 100644 MCP/tools/search/search_issues_and_pull_requests.go create mode 100644 MCP/tools/search/search_labels.go create mode 100644 MCP/tools/search/search_repos.go create mode 100644 MCP/tools/search/search_topics.go create mode 100644 MCP/tools/search/search_users.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_create_push_protection_bypass.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_get_alert.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_get_scan_history.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_list_alerts_for_enterprise.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_list_alerts_for_org.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_list_alerts_for_repo.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_list_locations_for_alert.go create mode 100644 MCP/tools/secret_scanning/secret_scanning_update_alert.go create mode 100644 MCP/tools/security_advisories/security_advisories_create_fork.go create mode 100644 MCP/tools/security_advisories/security_advisories_create_private_vulnerability_report.go create mode 100644 MCP/tools/security_advisories/security_advisories_create_repository_advisory.go create mode 100644 MCP/tools/security_advisories/security_advisories_create_repository_advisory_cve_request.go create mode 100644 MCP/tools/security_advisories/security_advisories_get_global_advisory.go create mode 100644 MCP/tools/security_advisories/security_advisories_get_repository_advisory.go create mode 100644 MCP/tools/security_advisories/security_advisories_list_global_advisories.go create mode 100644 MCP/tools/security_advisories/security_advisories_list_org_repository_advisories.go create mode 100644 MCP/tools/security_advisories/security_advisories_list_repository_advisories.go create mode 100644 MCP/tools/security_advisories/security_advisories_update_repository_advisory.go create mode 100644 MCP/tools/teams/teams_add_member_legacy.go create mode 100644 MCP/tools/teams/teams_add_or_update_membership_for_user_in_org.go create mode 100644 MCP/tools/teams/teams_add_or_update_membership_for_user_legacy.go create mode 100644 MCP/tools/teams/teams_add_or_update_project_permissions_in_org.go create mode 100644 MCP/tools/teams/teams_add_or_update_project_permissions_legacy.go create mode 100644 MCP/tools/teams/teams_add_or_update_repo_permissions_in_org.go create mode 100644 MCP/tools/teams/teams_add_or_update_repo_permissions_legacy.go create mode 100644 MCP/tools/teams/teams_check_permissions_for_project_in_org.go create mode 100644 MCP/tools/teams/teams_check_permissions_for_project_legacy.go create mode 100644 MCP/tools/teams/teams_check_permissions_for_repo_in_org.go create mode 100644 MCP/tools/teams/teams_check_permissions_for_repo_legacy.go create mode 100644 MCP/tools/teams/teams_create.go create mode 100644 MCP/tools/teams/teams_create_discussion_comment_in_org.go create mode 100644 MCP/tools/teams/teams_create_discussion_comment_legacy.go create mode 100644 MCP/tools/teams/teams_create_discussion_in_org.go create mode 100644 MCP/tools/teams/teams_create_discussion_legacy.go create mode 100644 MCP/tools/teams/teams_delete_discussion_comment_in_org.go create mode 100644 MCP/tools/teams/teams_delete_discussion_comment_legacy.go create mode 100644 MCP/tools/teams/teams_delete_discussion_in_org.go create mode 100644 MCP/tools/teams/teams_delete_discussion_legacy.go create mode 100644 MCP/tools/teams/teams_delete_in_org.go create mode 100644 MCP/tools/teams/teams_delete_legacy.go create mode 100644 MCP/tools/teams/teams_get_by_name.go create mode 100644 MCP/tools/teams/teams_get_discussion_comment_in_org.go create mode 100644 MCP/tools/teams/teams_get_discussion_comment_legacy.go create mode 100644 MCP/tools/teams/teams_get_discussion_in_org.go create mode 100644 MCP/tools/teams/teams_get_discussion_legacy.go create mode 100644 MCP/tools/teams/teams_get_legacy.go create mode 100644 MCP/tools/teams/teams_get_member_legacy.go create mode 100644 MCP/tools/teams/teams_get_membership_for_user_in_org.go create mode 100644 MCP/tools/teams/teams_get_membership_for_user_legacy.go create mode 100644 MCP/tools/teams/teams_list.go create mode 100644 MCP/tools/teams/teams_list_child_in_org.go create mode 100644 MCP/tools/teams/teams_list_child_legacy.go create mode 100644 MCP/tools/teams/teams_list_discussion_comments_in_org.go create mode 100644 MCP/tools/teams/teams_list_discussion_comments_legacy.go create mode 100644 MCP/tools/teams/teams_list_discussions_in_org.go create mode 100644 MCP/tools/teams/teams_list_discussions_legacy.go create mode 100644 MCP/tools/teams/teams_list_for_authenticated_user.go create mode 100644 MCP/tools/teams/teams_list_members_in_org.go create mode 100644 MCP/tools/teams/teams_list_members_legacy.go create mode 100644 MCP/tools/teams/teams_list_pending_invitations_in_org.go create mode 100644 MCP/tools/teams/teams_list_pending_invitations_legacy.go create mode 100644 MCP/tools/teams/teams_list_projects_in_org.go create mode 100644 MCP/tools/teams/teams_list_projects_legacy.go create mode 100644 MCP/tools/teams/teams_list_repos_in_org.go create mode 100644 MCP/tools/teams/teams_list_repos_legacy.go create mode 100644 MCP/tools/teams/teams_remove_member_legacy.go create mode 100644 MCP/tools/teams/teams_remove_membership_for_user_in_org.go create mode 100644 MCP/tools/teams/teams_remove_membership_for_user_legacy.go create mode 100644 MCP/tools/teams/teams_remove_project_in_org.go create mode 100644 MCP/tools/teams/teams_remove_project_legacy.go create mode 100644 MCP/tools/teams/teams_remove_repo_in_org.go create mode 100644 MCP/tools/teams/teams_remove_repo_legacy.go create mode 100644 MCP/tools/teams/teams_update_discussion_comment_in_org.go create mode 100644 MCP/tools/teams/teams_update_discussion_comment_legacy.go create mode 100644 MCP/tools/teams/teams_update_discussion_in_org.go create mode 100644 MCP/tools/teams/teams_update_discussion_legacy.go create mode 100644 MCP/tools/teams/teams_update_in_org.go create mode 100644 MCP/tools/teams/teams_update_legacy.go create mode 100644 MCP/tools/users/users_add_email_for_authenticated_user.go create mode 100644 MCP/tools/users/users_add_social_account_for_authenticated_user.go create mode 100644 MCP/tools/users/users_block.go create mode 100644 MCP/tools/users/users_check_blocked.go create mode 100644 MCP/tools/users/users_check_following_for_user.go create mode 100644 MCP/tools/users/users_check_person_is_followed_by_authenticated.go create mode 100644 MCP/tools/users/users_create_gpg_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_create_public_ssh_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_create_ssh_signing_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_delete_attestations_bulk.go create mode 100644 MCP/tools/users/users_delete_attestations_by_id.go create mode 100644 MCP/tools/users/users_delete_attestations_by_subject_digest.go create mode 100644 MCP/tools/users/users_delete_email_for_authenticated_user.go create mode 100644 MCP/tools/users/users_delete_gpg_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_delete_public_ssh_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_delete_social_account_for_authenticated_user.go create mode 100644 MCP/tools/users/users_delete_ssh_signing_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_follow.go create mode 100644 MCP/tools/users/users_get_authenticated.go create mode 100644 MCP/tools/users/users_get_by_id.go create mode 100644 MCP/tools/users/users_get_by_username.go create mode 100644 MCP/tools/users/users_get_context_for_user.go create mode 100644 MCP/tools/users/users_get_gpg_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_get_public_ssh_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_get_ssh_signing_key_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list.go create mode 100644 MCP/tools/users/users_list_attestations.go create mode 100644 MCP/tools/users/users_list_attestations_bulk.go create mode 100644 MCP/tools/users/users_list_blocked_by_authenticated_user.go create mode 100644 MCP/tools/users/users_list_emails_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_followed_by_authenticated_user.go create mode 100644 MCP/tools/users/users_list_followers_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_followers_for_user.go create mode 100644 MCP/tools/users/users_list_following_for_user.go create mode 100644 MCP/tools/users/users_list_gpg_keys_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_gpg_keys_for_user.go create mode 100644 MCP/tools/users/users_list_public_emails_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_public_keys_for_user.go create mode 100644 MCP/tools/users/users_list_public_ssh_keys_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_social_accounts_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_social_accounts_for_user.go create mode 100644 MCP/tools/users/users_list_ssh_signing_keys_for_authenticated_user.go create mode 100644 MCP/tools/users/users_list_ssh_signing_keys_for_user.go create mode 100644 MCP/tools/users/users_set_primary_email_visibility_for_authenticated_user.go create mode 100644 MCP/tools/users/users_unblock.go create mode 100644 MCP/tools/users/users_unfollow.go create mode 100644 MCP/tools/users/users_update_authenticated.go diff --git a/MCP/README.md b/MCP/README.md new file mode 100644 index 0000000..23c89d5 --- /dev/null +++ b/MCP/README.md @@ -0,0 +1,208 @@ +# GitHub v3 REST API MCP Server + +This MCP (Model Content Protocol) server provides access to GitHub v3 REST API API functionality through HTTP, HTTPS, and STDIO transport modes. + +## Features + +- transport mode support (HTTP and STDIO) +- Dynamic configuration through HTTP headers +- Automatic tool generation from API documentation + +## Building the Project + +1. Ensure you have Go 1.24.4 or later installed +2. Clone the repository +3. Build the project: + +```bash +go build -o mcp-server +``` + +## Running the Server + +The server can run in three modes based on the **TRANSPORT** environment variable: + +### HTTP Mode + +To run in HTTP mode, set the transport environment variable to "http" or "HTTP": + +```bash +export TRANSPORT="http" # or "HTTP" or "HTTPS" +export PORT="8181" # required +``` + +Run the server: +```bash +./mcp-server +``` + +#### Required Environment Variables for HTTP Mode: +- `TRANSPORT`: Set to "HTTP" **(Required)** +- `PORT`: Server port **(Required)** + +#### Configuration through HTTP Headers: +In HTTP mode, API configuration is provided via HTTP headers for each request: +- `API_BASE_URL`: **(Required)** Base URL for the API +- `BEARER_TOKEN`: Bearer token for authentication +- `API_KEY`: API key for authentication +- `BASIC_AUTH`: Basic authentication credentials + +Cursor mcp.json settings: + +{ + "mcpServers": { + "your-mcp-server-http": { + "url": "http://:/mcp", + "headers": { + "API_BASE_URL": "https://your-api-base-url", + "BEARER_TOKEN": "your-bearer-token" + } + } + } +} + +The server will start on the configured port with the following endpoints: +- `/mcp`: HTTP endpoint for MCP communication (requires API_BASE_URL header) +- `/`: Health check endpoint + +**Note**: At least one authentication header (BEARER_TOKEN, API_KEY, or BASIC_AUTH) should be provided unless the API explicitly doesn't require authentication. + +### HTTPS Mode + +To run in HTTPS mode, set the transport environment variable to "https" or "HTTPS": + +```bash +export TRANSPORT="https" # or "HTTPS" +export PORT="8443" # required +export CERT_FILE="./certs/cert.pem" # required +export KEY_FILE="./certs/key.pem" # required +``` + +Run the server: +```bash +./mcp-server +``` + +#### Required Environment Variables for HTTPS Mode: +- `TRANSPORT`: Set to "HTTPS" **(Required)** +- `PORT`: Server port **(Required)** +- `CERT_FILE`: Path to SSL certificate file **(Required)** +- `KEY_FILE`: Path to SSL private key file **(Required)** + +#### Configuration through HTTP Headers: +In HTTPS mode, API configuration is provided via HTTP headers for each request: +- `API_BASE_URL`: **(Required)** Base URL for the API +- `BEARER_TOKEN`: Bearer token for authentication +- `API_KEY`: API key for authentication +- `BASIC_AUTH`: Basic authentication credentials + +Cursor mcp.json settings: + +{ + "mcpServers": { + "your-mcp-server-https": { + "url": "https://:/mcp", + "headers": { + "API_BASE_URL": "https://your-api-base-url", + "BEARER_TOKEN": "your-bearer-token" + } + } + } +} + +The server will start on the configured port with the following endpoints: +- `/mcp`: HTTPS endpoint for MCP communication (requires API_BASE_URL header) +- `/`: Health check endpoint + +**Note**: At least one authentication header (BEARER_TOKEN, API_KEY, or BASIC_AUTH) should be provided unless the API explicitly doesn't require authentication. + +``` + +### STDIO Mode + +To run in STDIO mode, either set the transport environment variable to "stdio" or leave it unset (default): + +```bash +export TRANSPORT="stdio" # or leave unset for default +export API_BASE_URL="https://your-api-base-url" +export BEARER_TOKEN="your-bearer-token" +``` + +Run the server: +```bash +./mcp-server +``` + +#### Required Environment Variables for STDIO Mode: +- `TRANSPORT`: Set to "stdio" or leave unset (default) +- `API_BASE_URL`: Base URL for the API **(Required)** +- `BEARER_TOKEN`: Bearer token for authentication +- `API_KEY`: API key for authentication +- `BASIC_AUTH`: Basic authentication credentials + +**Note**: At least one authentication environment variable (BEARER_TOKEN, API_KEY, or BASIC_AUTH) should be provided unless the API explicitly doesn't require authentication. + +Cursor mcp.json settings: + +{ + "mcpServers": { + "your-mcp-server-stdio": { + "command": "/", + "env": { + "API_BASE_URL": "", + "BEARER_TOKEN": "" + } + } + } +} + +## Environment Variable Case Sensitivity + +The server supports both uppercase and lowercase transport environment variables: +- `TRANSPORT` (uppercase) - checked first +- `transport` (lowercase) - fallback if uppercase not set + +Valid values: "http", "HTTP", "https", "HTTPS", "stdio", or unset (defaults to STDIO) + +## Authentication + +### HTTP Mode +Authentication is provided through HTTP headers on each request: +- `BEARER_TOKEN`: Bearer token +- `API_KEY`: API key +- `BASIC_AUTH`: Basic authentication + +### STDIO Mode +Authentication is provided through environment variables: +- `BEARER_TOKEN`: Bearer token +- `API_KEY`: API key +- `BASIC_AUTH`: Basic authentication + +## Health Check + +When running in HTTP mode, you can check server health at the root endpoint (`/`). +Expected response: `{"status":"ok"}` + +## Transport Modes Summary + +### HTTP Mode (TRANSPORT=http or TRANSPORT=HTTP) +- Uses streamable HTTP server +- Configuration provided via HTTP headers for each request +- Requires API_BASE_URL header for each request +- Endpoint: `/mcp` +- Port configured via PORT environment variable (defaults to 8080) + +### HTTPS Mode (TRANSPORT=https or TRANSPORT=HTTPS) +- Uses streamable HTTPS server with SSL/TLS encryption +- Configuration provided via HTTP headers for each request +- Requires API_BASE_URL header for each request +- Endpoint: `/mcp` +- Port configured via PORT environment variable (defaults to 8443) +- **Requires SSL certificate and private key files (CERT_FILE and KEY_FILE)** + +### STDIO Mode (TRANSPORT=stdio or unset) +- Uses standard input/output for communication +- Configuration through environment variables only +- Requires API_BASE_URL environment variable +- Suitable for command-line usage + diff --git a/MCP/config/config.go b/MCP/config/config.go new file mode 100644 index 0000000..d8fc813 --- /dev/null +++ b/MCP/config/config.go @@ -0,0 +1,48 @@ +package config + +import ( + "fmt" + "os" +) + +type APIConfig struct { + BaseURL string + BearerToken string // For OAuth2/Bearer authentication + APIKey string // For API key authentication + BasicAuth string // For basic authentication + Port string // For server port configuration +} + +func LoadAPIConfig() (*APIConfig, error) { + // Check port environment variable (both uppercase and lowercase) + port := os.Getenv("PORT") + if port == "" { + port = os.Getenv("port") + } + + baseURL := os.Getenv("API_BASE_URL") + + // Check transport environment variable (both uppercase and lowercase) + transport := os.Getenv("TRANSPORT") + if transport == "" { + transport = os.Getenv("transport") + } + + // For STDIO mode (transport is not "http"/"HTTP"/"https"/"HTTPS"), API_BASE_URL is required from environment + if transport != "http" && transport != "HTTP" && transport != "https" && transport != "HTTPS" && baseURL == "" { + return nil, fmt.Errorf("API_BASE_URL environment variable not set") + } + + // For HTTP/HTTPS mode (transport is "http"/"HTTP"/"https"/"HTTPS"), API_BASE_URL comes from headers + // so we don't require it from environment variables + + return &APIConfig{ + BaseURL: baseURL, + BearerToken: os.Getenv("BEARER_TOKEN"), + APIKey: os.Getenv("API_KEY"), + BasicAuth: os.Getenv("BASIC_AUTH"), + Port: port, + }, nil +} + + diff --git a/MCP/go.mod b/MCP/go.mod new file mode 100644 index 0000000..ca1c733 --- /dev/null +++ b/MCP/go.mod @@ -0,0 +1,17 @@ +module github.com/github-v3-rest-api/mcp-server + +go 1.24.4 + +require github.com/mark3labs/mcp-go v0.37.0 + +require ( + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/invopop/jsonschema v0.13.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/spf13/cast v1.7.1 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect + github.com/yosida95/uritemplate/v3 v3.0.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/MCP/go.sum b/MCP/go.sum new file mode 100644 index 0000000..6a2363e --- /dev/null +++ b/MCP/go.sum @@ -0,0 +1,39 @@ +github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= +github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E= +github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mark3labs/mcp-go v0.37.0 h1:BywvZLPRT6Zx6mMG/MJfxLSZQkTGIcJSEGKsvr4DsoQ= +github.com/mark3labs/mcp-go v0.37.0/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y= +github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= +github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= +github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/MCP/main.go b/MCP/main.go new file mode 100644 index 0000000..28d426f --- /dev/null +++ b/MCP/main.go @@ -0,0 +1,145 @@ +package main + +import ( + "context" + "log" + "net" + "net/http" + "os" + "os/signal" + "syscall" + "time" + + "github.com/mark3labs/mcp-go/server" + "github.com/github-v3-rest-api/mcp-server/config" +) + +func main() { + cfg, err := config.LoadAPIConfig() + if err != nil { + log.Fatalf("Failed to load config: %v", err) + } + + // Check transport environment variable (both uppercase and lowercase) + transport := os.Getenv("TRANSPORT") + if transport == "" { + transport = os.Getenv("transport") + } + sigChan := make(chan os.Signal, 1) + signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) + + // HTTP/HTTPS Mode - if transport is "http", "HTTP", "https", or "HTTPS" + if transport == "http" || transport == "HTTP" || transport == "https" || transport == "HTTPS" { + port := cfg.Port + if port == "" { + log.Fatalf("PORT environment variable is required for HTTP/HTTPS mode. Please set PORT environment variable.") + } + + // Determine if HTTPS mode and normalize transport + isHTTPS := transport == "https" || transport == "HTTPS" + if isHTTPS { + transport = "HTTPS" + } else { + transport = "HTTP" + } + + log.Printf("Running in %s mode on port %s", transport, port) + + mux := http.NewServeMux() + mux.HandleFunc("/mcp", func(w http.ResponseWriter, r *http.Request) { + // Read headers for dynamic config + apiCfg := &config.APIConfig{ + BaseURL: r.Header.Get("API_BASE_URL"), + BearerToken: r.Header.Get("BEARER_TOKEN"), + APIKey: r.Header.Get("API_KEY"), + BasicAuth: r.Header.Get("BASIC_AUTH"), + } + + if apiCfg.BaseURL == "" { + http.Error(w, "Missing API_BASE_URL header", http.StatusBadRequest) + return + } + + log.Printf("Incoming HTTP request - BaseURL: %s", apiCfg.BaseURL) + + // Create MCP server for this request + mcpSrv := createMCPServer(apiCfg, transport) + handler := server.NewStreamableHTTPServer(mcpSrv, server.WithHTTPContextFunc( + func(ctx context.Context, req *http.Request) context.Context { + return context.WithValue(ctx, "apiConfig", apiCfg) + }, + )) + + handler.ServeHTTP(w, r) + }) + + mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(`{"status":"ok"}`)) + }) + + addr := net.JoinHostPort("0.0.0.0", port) + httpServer := &http.Server{Addr: addr, Handler: mux} + + go func() { + // Check if HTTPS mode + if isHTTPS { + certFile := os.Getenv("CERT_FILE") + keyFile := os.Getenv("KEY_FILE") + + if certFile == "" || keyFile == "" { + log.Fatalf("CERT_FILE and KEY_FILE environment variables are required for HTTPS mode") + } + + log.Printf("Starting HTTPS server on %s", addr) + if err := httpServer.ListenAndServeTLS(certFile, keyFile); err != http.ErrServerClosed { + log.Fatalf("HTTPS server error: %v", err) + } + } else { + log.Printf("Starting HTTP server on %s", addr) + if err := httpServer.ListenAndServe(); err != http.ErrServerClosed { + log.Fatalf("HTTP server error: %v", err) + } + } + }() + + <-sigChan + log.Println("Shutdown signal received") + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := httpServer.Shutdown(ctx); err != nil { + log.Printf("Shutdown error: %v", err) + } else { + log.Println("HTTP server shutdown complete") + } + return + } + + // STDIO Mode - default when no transport or transport is "stdio" + log.Println("Running in STDIO mode") + mcp := createMCPServer(cfg, "STDIO") + go func() { + if err := server.ServeStdio(mcp); err != nil { + log.Fatalf("STDIO error: %v", err) + } + }() + <-sigChan + log.Println("Received shutdown signal. Exiting STDIO mode.") +} + +func createMCPServer(cfg *config.APIConfig, mode string) *server.MCPServer { + mcp := server.NewMCPServer("GitHub v3 REST API", "1.1.4", + server.WithToolCapabilities(true), + server.WithRecovery(), + ) + + tools := GetAll(cfg) + log.Printf("Loaded %d tools for %s mode", len(tools), mode) + + for _, tool := range tools { + mcp.AddTool(tool.Definition, tool.Handler) + } + + return mcp +} \ No newline at end of file diff --git a/MCP/models/models.go b/MCP/models/models.go new file mode 100644 index 0000000..788f559 --- /dev/null +++ b/MCP/models/models.go @@ -0,0 +1,10131 @@ +package models + +import ( + "context" + "github.com/mark3labs/mcp-go/mcp" +) + +type Tool struct { + Definition mcp.Tool + Handler func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Release Webhooksrelease `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Editors []map[string]interface{} `json:"editors,omitempty"` + Languages []map[string]interface{} `json:"languages,omitempty"` // Code completion metrics for active languages. + Total_engaged_users int `json:"total_engaged_users,omitempty"` // Number of users who accepted at least one Copilot code suggestion, across all active editors. Includes both full and partial acceptances. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Selected_actions_url string `json:"selected_actions_url,omitempty"` // The API URL to use to get or set the actions and reusable workflows that are allowed to run, when `allowed_actions` is set to `selected`. + Selected_repositories_url string `json:"selected_repositories_url,omitempty"` // The API URL to use to get or set the selected repositories that are allowed to run GitHub Actions, when `enabled_repositories` is set to `selected`. + Allowed_actions string `json:"allowed_actions,omitempty"` // The permissions policy that controls the actions and reusable workflows that are allowed to run. + Enabled_repositories string `json:"enabled_repositories"` // The policy that controls the repositories in the organization that are allowed to run GitHub Actions. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Context string `json:"context"` // The status check context name that must be present on the commit. + Integration_id int `json:"integration_id,omitempty"` // The optional integration ID that this status check must originate from. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Uniques int `json:"uniques"` + Count int `json:"count"` + Path string `json:"path"` + Title string `json:"title"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Permission string `json:"permission"` + Html_url string `json:"html_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Url string `json:"url"` + Assignment string `json:"assignment,omitempty"` // Determines if the team has a direct, indirect, or mixed relationship to a role + Parent GeneratedType `json:"parent"` // Groups of organization members that gives permissions on specified repositories. + Members_url string `json:"members_url"` + Node_id string `json:"node_id"` + Privacy string `json:"privacy,omitempty"` + Repositories_url string `json:"repositories_url"` + Slug string `json:"slug"` + Name string `json:"name"` + Description string `json:"description"` + Id int `json:"id"` + Notification_setting string `json:"notification_setting,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Received_events_url string `json:"received_events_url"` + Site_admin bool `json:"site_admin"` + Followers_url string `json:"followers_url"` + Html_url string `json:"html_url"` + Url string `json:"url"` + Events_url string `json:"events_url"` + Following_url string `json:"following_url"` + TypeField string `json:"type"` + Email string `json:"email,omitempty"` + Gists_url string `json:"gists_url"` + Avatar_url string `json:"avatar_url"` + Login string `json:"login"` + Name string `json:"name,omitempty"` + Starred_url string `json:"starred_url"` + Gravatar_id string `json:"gravatar_id"` + Id int64 `json:"id"` + User_view_type string `json:"user_view_type,omitempty"` + Repos_url string `json:"repos_url"` + Node_id string `json:"node_id"` + Subscriptions_url string `json:"subscriptions_url"` + Role_name string `json:"role_name"` + Organizations_url string `json:"organizations_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Review map[string]interface{} `json:"review"` // The review that was affected. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Master_branch string `json:"master_branch"` // The name of the repository's default branch (usually `main`). + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender"` // A GitHub user. + Pusher_type string `json:"pusher_type"` // The pusher type for the event. Can be either `user` or a deploy key. + Ref string `json:"ref"` // The [`git ref`](https://docs.github.com/rest/git/refs#get-a-reference) resource. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Ref_type string `json:"ref_type"` // The type of Git ref object created in the repository. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Description string `json:"description"` // The repository's current description. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Rate_limited_request_count int64 `json:"rate_limited_request_count,omitempty"` // The total number of requests that were rate limited within the queried time period + Total_request_count int64 `json:"total_request_count,omitempty"` // The total number of requests within the queried time period +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Completed int `json:"completed"` + Percent_completed int `json:"percent_completed"` + Total int `json:"total"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Closed_issues int `json:"closed_issues"` + Id int `json:"id"` + Closed_at string `json:"closed_at"` + Title string `json:"title"` // The title of the milestone. + Labels_url string `json:"labels_url"` + Updated_at string `json:"updated_at"` + Due_on string `json:"due_on"` + Open_issues int `json:"open_issues"` + Html_url string `json:"html_url"` + Url string `json:"url"` + Created_at string `json:"created_at"` + Description string `json:"description"` + Node_id string `json:"node_id"` + Number int `json:"number"` // The number of the milestone. + State string `json:"state"` // The state of the milestone. + Creator GeneratedType `json:"creator"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Body_html string `json:"body_html"` + Private bool `json:"private"` // Whether or not this discussion should be restricted to team members and organization owners. + Updated_at string `json:"updated_at"` + Author GeneratedType `json:"author"` // A GitHub user. + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Comments_count int `json:"comments_count"` + Pinned bool `json:"pinned"` // Whether or not this discussion should be pinned for easy retrieval. + Team_url string `json:"team_url"` + Comments_url string `json:"comments_url"` + Url string `json:"url"` + Html_url string `json:"html_url"` + Last_edited_at string `json:"last_edited_at"` + Number int `json:"number"` // The unique sequence number of a team discussion. + Reactions GeneratedType `json:"reactions,omitempty"` + Title string `json:"title"` // The title of the discussion. + Body string `json:"body"` // The main text of the discussion. + Body_version string `json:"body_version"` // The current version of the body content. If provided, this update operation will be rejected if the given version does not match the latest version on the server. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Deleted_by GeneratedType `json:"deleted_by"` // A GitHub user. + Number int `json:"number"` + Public bool `json:"public"` + Short_description string `json:"short_description"` + Title string `json:"title"` + Closed_at string `json:"closed_at"` + Description string `json:"description"` + Id float64 `json:"id"` + Created_at string `json:"created_at"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Node_id string `json:"node_id"` + Deleted_at string `json:"deleted_at"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Release Webhooksrelease `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Models []map[string]interface{} `json:"models,omitempty"` // List of model metrics for a custom models and the default model. + Total_engaged_users int `json:"total_engaged_users,omitempty"` // Total number of users who prompted Copilot Chat on github.com at least once. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert Webhooksalert `json:"alert"` // The security alert of the vulnerable dependency. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Forkee interface{} `json:"forkee"` // The created [`repository`](https://docs.github.com/rest/repos/repos#get-a-repository) resource. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Starred_at string `json:"starred_at"` // The time the star was created. This is a timestamp in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. Will be `null` for the `deleted` action. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Effective_date string `json:"effective_date"` + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + Previous_marketplace_purchase Webhookspreviousmarketplacepurchase `json:"previous_marketplace_purchase,omitempty"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Token_name string `json:"token_name"` // The name given to the user's token. This field can also be found in an organization's settings page for Active Tokens. + Permissions map[string]interface{} `json:"permissions"` // Permissions requested, categorized by type of permission. + Repository_selection string `json:"repository_selection"` // Type of repository selection requested. + Token_expired bool `json:"token_expired"` // Whether the associated fine-grained personal access token has expired. + Repositories_url string `json:"repositories_url"` // URL to the list of repositories the fine-grained personal access token can access. Only follow when `repository_selection` is `subset`. + Token_expires_at string `json:"token_expires_at"` // Date and time when the associated fine-grained personal access token expires. + Access_granted_at string `json:"access_granted_at"` // Date and time when the fine-grained personal access token was approved to access the organization. + Token_last_used_at string `json:"token_last_used_at"` // Date and time when the associated fine-grained personal access token was last used for authentication. + Id int `json:"id"` // Unique identifier of the fine-grained personal access token grant. The `pat_id` used to get details about an approved fine-grained personal access token. + Owner GeneratedType `json:"owner"` // A GitHub user. + Token_id int `json:"token_id"` // Unique identifier of the user's token. This field can also be found in audit log events and the organization's settings for their PAT grants. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Project Webhooksproject `json:"project"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alert GeneratedType `json:"alert"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Errors []map[string]interface{} `json:"errors"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Accepted bool `json:"accepted"` // Whether the user has accepted the permissions defined by the devcontainer config +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repo Repository `json:"repo"` // A repository on GitHub. + Starred_at string `json:"starred_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Billable map[string]interface{} `json:"billable"` +} + +// Discussion represents the Discussion schema from the OpenAPI specification +type Discussion struct { + Number int `json:"number"` + State_reason string `json:"state_reason"` // The reason for the current state + Html_url string `json:"html_url"` + Active_lock_reason string `json:"active_lock_reason"` + Updated_at string `json:"updated_at"` + Answer_chosen_by map[string]interface{} `json:"answer_chosen_by"` + Answer_html_url string `json:"answer_html_url"` + Created_at string `json:"created_at"` + State string `json:"state"` // The current state of the discussion. `converting` means that the discussion is being converted from an issue. `transferring` means that the discussion is being transferred from another repository. + Author_association string `json:"author_association"` // How the author is associated with the repository. + Locked bool `json:"locked"` + Id int `json:"id"` + Repository_url string `json:"repository_url"` + Answer_chosen_at string `json:"answer_chosen_at"` + Category map[string]interface{} `json:"category"` + Body string `json:"body"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + Timeline_url string `json:"timeline_url,omitempty"` + Labels []Label `json:"labels,omitempty"` + Node_id string `json:"node_id"` + Title string `json:"title"` + Comments int `json:"comments"` + User map[string]interface{} `json:"user"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Days_left_in_billing_cycle int `json:"days_left_in_billing_cycle"` // Numbers of days left in billing cycle. + Estimated_paid_storage_for_month int `json:"estimated_paid_storage_for_month"` // Estimated storage space (GB) used in billing cycle. + Estimated_storage_for_month int `json:"estimated_storage_for_month"` // Estimated sum of free and paid storage space (GB) used in billing cycle. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Code int `json:"code"` + Message string `json:"message"` + Status string `json:"status"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alert GeneratedType `json:"alert"` // A Dependabot alert. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Inactive_this_cycle int `json:"inactive_this_cycle,omitempty"` // The number of seats that have not used Copilot during the current billing cycle. + Pending_cancellation int `json:"pending_cancellation,omitempty"` // The number of seats that are pending cancellation at the end of the current billing cycle. + Pending_invitation int `json:"pending_invitation,omitempty"` // The number of users who have been invited to receive a Copilot seat through this organization. + Total int `json:"total,omitempty"` // The total number of seats being billed for the organization as of the current billing cycle. + Active_this_cycle int `json:"active_this_cycle,omitempty"` // The number of seats that have used Copilot during the current billing cycle. + Added_this_cycle int `json:"added_this_cycle,omitempty"` // Seats added during the current billing cycle. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Release Webhooksrelease1 `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Href string `json:"href"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request GeneratedType `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// Webhooksusermannequin represents the Webhooksusermannequin schema from the OpenAPI specification +type Webhooksusermannequin struct { + Email string `json:"email,omitempty"` + Following_url string `json:"following_url,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Name string `json:"name,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + Followers_url string `json:"followers_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + Url string `json:"url,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Login string `json:"login"` + Gists_url string `json:"gists_url,omitempty"` + Repos_url string `json:"repos_url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Deleted bool `json:"deleted,omitempty"` + Events_url string `json:"events_url,omitempty"` + TypeField string `json:"type,omitempty"` + Id int `json:"id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Clones []Traffic `json:"clones"` + Count int `json:"count"` + Uniques int `json:"uniques"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Label Webhookslabel `json:"label"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// Webhooksprojectcolumn represents the Webhooksprojectcolumn schema from the OpenAPI specification +type Webhooksprojectcolumn struct { + Node_id string `json:"node_id"` + Name string `json:"name"` // Name of the project column + Url string `json:"url"` + Created_at string `json:"created_at"` + Project_url string `json:"project_url"` + Updated_at string `json:"updated_at"` + After_id int `json:"after_id,omitempty"` + Id int `json:"id"` // The unique identifier of the project column + Cards_url string `json:"cards_url"` +} + +// Webhooksmarketplacepurchase represents the Webhooksmarketplacepurchase schema from the OpenAPI specification +type Webhooksmarketplacepurchase struct { + Account map[string]interface{} `json:"account"` + Billing_cycle string `json:"billing_cycle"` + Free_trial_ends_on string `json:"free_trial_ends_on"` + Next_billing_date string `json:"next_billing_date"` + On_free_trial bool `json:"on_free_trial"` + Plan map[string]interface{} `json:"plan"` + Unit_count int `json:"unit_count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Health_percentage int `json:"health_percentage"` + Updated_at string `json:"updated_at"` + Content_reports_enabled bool `json:"content_reports_enabled,omitempty"` + Description string `json:"description"` + Documentation string `json:"documentation"` + Files map[string]interface{} `json:"files"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes,omitempty"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_card interface{} `json:"project_card"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Color string `json:"color"` + Name string `json:"name"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id string `json:"id"` // The ID of the GitHub Pages deployment. This is the Git SHA of the deployed commit. + Page_url string `json:"page_url"` // The URI to the deployed GitHub Pages. + Preview_url string `json:"preview_url,omitempty"` // The URI to the deployed GitHub Pages preview. + Status_url string `json:"status_url"` // The URI to monitor GitHub Pages deployment status. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Following int `json:"following"` + Login string `json:"login"` + Blog string `json:"blog"` + Repos_url string `json:"repos_url"` + Plan map[string]interface{} `json:"plan,omitempty"` + Following_url string `json:"following_url"` + Twitter_username string `json:"twitter_username,omitempty"` + Gravatar_id string `json:"gravatar_id"` + Node_id string `json:"node_id"` + Subscriptions_url string `json:"subscriptions_url"` + User_view_type string `json:"user_view_type,omitempty"` + Company string `json:"company"` + Collaborators int `json:"collaborators,omitempty"` + Html_url string `json:"html_url"` + Hireable bool `json:"hireable"` + Public_gists int `json:"public_gists"` + Owned_private_repos int `json:"owned_private_repos,omitempty"` + Disk_usage int `json:"disk_usage,omitempty"` + Avatar_url string `json:"avatar_url"` + Created_at string `json:"created_at"` + Gists_url string `json:"gists_url"` + Notification_email string `json:"notification_email,omitempty"` + Id int64 `json:"id"` + Name string `json:"name"` + Events_url string `json:"events_url"` + Received_events_url string `json:"received_events_url"` + TypeField string `json:"type"` + Total_private_repos int `json:"total_private_repos,omitempty"` + Url string `json:"url"` + Updated_at string `json:"updated_at"` + Followers int `json:"followers"` + Bio string `json:"bio"` + Email string `json:"email"` + Organizations_url string `json:"organizations_url"` + Private_gists int `json:"private_gists,omitempty"` + Followers_url string `json:"followers_url"` + Site_admin bool `json:"site_admin"` + Location string `json:"location"` + Public_repos int `json:"public_repos"` + Starred_url string `json:"starred_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Added_by string `json:"added_by,omitempty"` + Id int `json:"id"` + Key string `json:"key"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Enabled bool `json:"enabled,omitempty"` + Last_used string `json:"last_used,omitempty"` + Read_only bool `json:"read_only"` + Title string `json:"title"` + Verified bool `json:"verified"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Alert GeneratedType `json:"alert"` // A Dependabot alert. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Label Webhookslabel `json:"label"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` // The action that was performed. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Seat_management_setting string `json:"seat_management_setting"` // The mode of assigning new seats. + Cli string `json:"cli,omitempty"` // The organization policy for allowing or disallowing Copilot in the CLI. + Ide_chat string `json:"ide_chat,omitempty"` // The organization policy for allowing or disallowing Copilot Chat in the IDE. + Plan_type string `json:"plan_type,omitempty"` // The Copilot plan of the organization, or the parent enterprise, when applicable. + Platform_chat string `json:"platform_chat,omitempty"` // The organization policy for allowing or disallowing Copilot features on GitHub.com. + Public_code_suggestions string `json:"public_code_suggestions"` // The organization policy for allowing or blocking suggestions matching public code (duplication detection filter). + Seat_breakdown GeneratedType `json:"seat_breakdown"` // The breakdown of Copilot Business seats for the organization. +} + +// Event represents the Event schema from the OpenAPI specification +type Event struct { + Id string `json:"id"` + Org Actor `json:"org,omitempty"` // Actor + Payload map[string]interface{} `json:"payload"` + Public bool `json:"public"` + Repo map[string]interface{} `json:"repo"` + TypeField string `json:"type"` + Actor Actor `json:"actor"` // Actor + Created_at string `json:"created_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Include_claim_keys []string `json:"include_claim_keys,omitempty"` // Array of unique strings. Each claim key can only contain alphanumeric characters and underscores. + Use_default bool `json:"use_default"` // Whether to use the default template or not. If `true`, the `include_claim_keys` field is ignored. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Filename string `json:"filename"` + Raw_url string `json:"raw_url"` + Blob_url string `json:"blob_url"` + Contents_url string `json:"contents_url"` + Additions int `json:"additions"` + Deletions int `json:"deletions"` + Patch string `json:"patch,omitempty"` + Previous_filename string `json:"previous_filename,omitempty"` + Sha string `json:"sha"` + Status string `json:"status"` + Changes int `json:"changes"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` // The unique identifier of the deployment protection rule integration. + Integration_url string `json:"integration_url"` // The URL for the endpoint to get details about the app. + Node_id string `json:"node_id"` // The node ID for the deployment protection rule integration. + Slug string `json:"slug"` // The slugified name of the deployment protection rule integration. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_count int `json:"repository_count"` // The total number of repositories that were skipped for this reason. + Repositories []GeneratedType `json:"repositories"` // A list of repositories that were skipped. This list may not include all repositories that were skipped. This is only available when the repository was found and the user has access to it. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enabled bool `json:"enabled"` // Whether GitHub Actions is enabled on the repository. + Selected_actions_url string `json:"selected_actions_url,omitempty"` // The API URL to use to get or set the actions and reusable workflows that are allowed to run, when `allowed_actions` is set to `selected`. + Allowed_actions string `json:"allowed_actions,omitempty"` // The permissions policy that controls the actions and reusable workflows that are allowed to run. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Response map[string]interface{} `json:"response"` + Url string `json:"url,omitempty"` // The URL target of the delivery. + Action string `json:"action"` // The type of activity for the event that triggered the delivery. + Delivered_at string `json:"delivered_at"` // Time when the delivery was delivered. + Redelivery bool `json:"redelivery"` // Whether the delivery is a redelivery. + Request map[string]interface{} `json:"request"` + Status_code int `json:"status_code"` // Status code received when delivery was made. + Id int `json:"id"` // Unique identifier of the delivery. + Installation_id int `json:"installation_id"` // The id of the GitHub App installation associated with this event. + Event string `json:"event"` // The event that triggered the delivery. + Duration float64 `json:"duration"` // Time spent delivering. + Status string `json:"status"` // Description of the status of the attempted delivery + Throttled_at string `json:"throttled_at,omitempty"` // Time when the webhook delivery was throttled. + Repository_id int `json:"repository_id"` // The id of the repository associated with this event. + Guid string `json:"guid"` // Unique identifier for the event (shared with all deliveries for all webhooks that subscribe to this event). +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Starred_at string `json:"starred_at,omitempty"` + Events_url string `json:"events_url"` + Login string `json:"login"` + Subscriptions_url string `json:"subscriptions_url"` + Html_url string `json:"html_url"` + Starred_url string `json:"starred_url"` + TypeField string `json:"type"` + User_view_type string `json:"user_view_type,omitempty"` + Url string `json:"url"` + Email string `json:"email,omitempty"` + Id int64 `json:"id"` + Followers_url string `json:"followers_url"` + Following_url string `json:"following_url"` + Name string `json:"name,omitempty"` + Received_events_url string `json:"received_events_url"` + Site_admin bool `json:"site_admin"` + Avatar_url string `json:"avatar_url"` + Gravatar_id string `json:"gravatar_id"` + Organizations_url string `json:"organizations_url"` + Gists_url string `json:"gists_url"` + Repos_url string `json:"repos_url"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Received_events_url string `json:"received_events_url"` + Suspended_at string `json:"suspended_at,omitempty"` + Score float64 `json:"score"` + Blog string `json:"blog,omitempty"` + Hireable bool `json:"hireable,omitempty"` + Gists_url string `json:"gists_url"` + Following_url string `json:"following_url"` + Bio string `json:"bio,omitempty"` + Repos_url string `json:"repos_url"` + Id int64 `json:"id"` + Url string `json:"url"` + Updated_at string `json:"updated_at,omitempty"` + Gravatar_id string `json:"gravatar_id"` + Followers_url string `json:"followers_url"` + Name string `json:"name,omitempty"` + Subscriptions_url string `json:"subscriptions_url"` + Public_repos int `json:"public_repos,omitempty"` + Avatar_url string `json:"avatar_url"` + Html_url string `json:"html_url"` + Login string `json:"login"` + Organizations_url string `json:"organizations_url"` + Created_at string `json:"created_at,omitempty"` + Followers int `json:"followers,omitempty"` + Location string `json:"location,omitempty"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + TypeField string `json:"type"` + Following int `json:"following,omitempty"` + Email string `json:"email,omitempty"` + Site_admin bool `json:"site_admin"` + Public_gists int `json:"public_gists,omitempty"` + Node_id string `json:"node_id"` + User_view_type string `json:"user_view_type,omitempty"` + Company string `json:"company,omitempty"` + Events_url string `json:"events_url"` + Starred_url string `json:"starred_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Target_type string `json:"target_type"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Account map[string]interface{} `json:"account"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` +} + +// Webhookschanges represents the Webhookschanges schema from the OpenAPI specification +type Webhookschanges struct { + Body map[string]interface{} `json:"body,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor GeneratedType `json:"actor"` // A GitHub user. + Url string `json:"url"` + Commit_id string `json:"commit_id"` + Commit_url string `json:"commit_url"` + Id int `json:"id"` + Milestone map[string]interface{} `json:"milestone"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Event string `json:"event"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. +} + +// Commit represents the Commit schema from the OpenAPI specification +type Commit struct { + Stats map[string]interface{} `json:"stats,omitempty"` + Url string `json:"url"` + Comments_url string `json:"comments_url"` + Files []GeneratedType `json:"files,omitempty"` + Sha string `json:"sha"` + Commit map[string]interface{} `json:"commit"` + Parents []map[string]interface{} `json:"parents"` + Author interface{} `json:"author"` + Committer interface{} `json:"committer"` + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Approver Webhooksapprover `json:"approver,omitempty"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Comment string `json:"comment,omitempty"` + Workflow_job_run Webhooksworkflowjobrun `json:"workflow_job_run,omitempty"` + Workflow_run map[string]interface{} `json:"workflow_run"` + Action string `json:"action"` + Reviewers []map[string]interface{} `json:"reviewers,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Since string `json:"since"` + Workflow_job_runs []map[string]interface{} `json:"workflow_job_runs,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Storage_in_bytes int `json:"storage_in_bytes"` // How much storage is available to the codespace. + Cpus int `json:"cpus"` // How many cores are available to the codespace. + Display_name string `json:"display_name"` // The display name of the machine includes cores, memory, and storage. + Memory_in_bytes int `json:"memory_in_bytes"` // How much memory is available to the codespace. + Name string `json:"name"` // The name of the machine. + Operating_system string `json:"operating_system"` // The operating system of the machine. + Prebuild_availability string `json:"prebuild_availability"` // Whether a prebuild is currently available when creating a codespace for this machine and repository. If a branch was not specified as a ref, the default branch will be assumed. Value will be "null" if prebuilds are not supported or prebuild availability could not be determined. Value will be "none" if no prebuild is available. Latest values "ready" and "in_progress" indicate the prebuild availability status. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Total_count int `json:"total_count"` // Total number of caches + Actions_caches []map[string]interface{} `json:"actions_caches"` // Array of caches +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Deployment Deployment `json:"deployment,omitempty"` // A request for a specific ref(branch,sha,tag) to be deployed + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow_job interface{} `json:"workflow_job"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Included_gigabytes_bandwidth int `json:"included_gigabytes_bandwidth"` // Free storage space (GB) for GitHub Packages. + Total_gigabytes_bandwidth_used int `json:"total_gigabytes_bandwidth_used"` // Sum of the free and paid storage space (GB) for GitHuub Packages. + Total_paid_gigabytes_bandwidth_used int `json:"total_paid_gigabytes_bandwidth_used"` // Total paid storage space (GB) for GitHuub Packages. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Status string `json:"status"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` + Reason string `json:"reason"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Scope string `json:"scope"` // The scope of the membership. Currently, can only be `team`. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Team Webhooksteam `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender map[string]interface{} `json:"sender"` + Member Webhooksuser `json:"member"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Status string `json:"status,omitempty"` // The current status of the deployment. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Path string `json:"path"` + Url string `json:"url"` + Git_url string `json:"git_url"` + Last_modified_at string `json:"last_modified_at,omitempty"` + Line_numbers []string `json:"line_numbers,omitempty"` + Name string `json:"name"` + Score float64 `json:"score"` + Language string `json:"language,omitempty"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Sha string `json:"sha"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + File_size int `json:"file_size,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion_comment_url string `json:"discussion_comment_url"` // The API URL to get the discussion comment where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Architecture string `json:"architecture"` + Download_url string `json:"download_url"` + Filename string `json:"filename"` + Os string `json:"os"` + Sha256_checksum string `json:"sha256_checksum,omitempty"` + Temp_download_token string `json:"temp_download_token,omitempty"` // A short lived bearer token used to download the runner, if needed. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` // A Dependabot alert. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository map[string]interface{} `json:"repository,omitempty"` // A git repository + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Team Webhooksteam1 `json:"team"` // Groups of organization members that gives permissions on specified repositories. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Private bool `json:"private"` // Whether the repository is private. + Stargazers_count int `json:"stargazers_count"` + Updated_at string `json:"updated_at"` + Full_name string `json:"full_name"` // The full, globally unique, name of the repository. + Id int `json:"id"` // A unique identifier of the repository. + Name string `json:"name"` // The name of the repository. +} + +// Webhookssponsorship represents the Webhookssponsorship schema from the OpenAPI specification +type Webhookssponsorship struct { + Sponsorable map[string]interface{} `json:"sponsorable"` + Tier map[string]interface{} `json:"tier"` // The `tier_changed` and `pending_tier_change` will include the original tier before the change or pending change. For more information, see the pending tier change payload. + Created_at string `json:"created_at"` + Maintainer map[string]interface{} `json:"maintainer,omitempty"` + Node_id string `json:"node_id"` + Privacy_level string `json:"privacy_level"` + Sponsor map[string]interface{} `json:"sponsor"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` // The action that was performed. + Assignee Webhooksuser `json:"assignee,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Team Webhooksteam1 `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Sync_to_organizations string `json:"sync_to_organizations,omitempty"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Slug string `json:"slug"` + Created_at string `json:"created_at"` + Group_name string `json:"group_name,omitempty"` + Id int64 `json:"id"` + Members_url string `json:"members_url"` + Name string `json:"name"` + Organization_selection_type string `json:"organization_selection_type,omitempty"` + Description string `json:"description,omitempty"` + Group_id string `json:"group_id,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. + Organization_url string `json:"organization_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Role string `json:"role"` // The user's membership type in the organization. + State string `json:"state"` // The state of the member in the organization. The `pending` state indicates the user has not yet accepted an invitation. + Url string `json:"url"` + User GeneratedType `json:"user"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Event string `json:"event,omitempty"` + Node_id string `json:"node_id,omitempty"` + Comments []GeneratedType `json:"comments,omitempty"` + Commit_id string `json:"commit_id,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Stargazers_count int `json:"stargazers_count"` + Size int `json:"size"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Forks_count int `json:"forks_count"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Ssh_url string `json:"ssh_url"` + Downloads_url string `json:"downloads_url"` + Git_commits_url string `json:"git_commits_url"` + Issues_url string `json:"issues_url"` + Updated_at string `json:"updated_at"` + Pulls_url string `json:"pulls_url"` + Trees_url string `json:"trees_url"` + Language string `json:"language"` + Contents_url string `json:"contents_url"` + Url string `json:"url"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Watchers int `json:"watchers"` + Archived bool `json:"archived"` // Whether the repository is archived. + Tags_url string `json:"tags_url"` + Fork bool `json:"fork"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Statuses_url string `json:"statuses_url"` + Full_name string `json:"full_name"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Merge_commit_message string `json:"merge_commit_message,omitempty"` // The default value for a merge commit message. - `PR_TITLE` - default to the pull request's title. - `PR_BODY` - default to the pull request's body. - `BLANK` - default to a blank commit message. + Mirror_url string `json:"mirror_url"` + Milestones_url string `json:"milestones_url"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Hooks_url string `json:"hooks_url"` + Comments_url string `json:"comments_url"` + Forks_url string `json:"forks_url"` + Releases_url string `json:"releases_url"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Svn_url string `json:"svn_url"` + Teams_url string `json:"teams_url"` + Code_search_index_status map[string]interface{} `json:"code_search_index_status,omitempty"` // The status of the code search index for this repository + Open_issues_count int `json:"open_issues_count"` + Keys_url string `json:"keys_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Topics []string `json:"topics,omitempty"` + Notifications_url string `json:"notifications_url"` + Issue_events_url string `json:"issue_events_url"` + Blobs_url string `json:"blobs_url"` + Contributors_url string `json:"contributors_url"` + License GeneratedType `json:"license"` // License Simple + Squash_merge_commit_title string `json:"squash_merge_commit_title,omitempty"` // The default value for a squash merge commit title: - `PR_TITLE` - default to the pull request's title. - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + Clone_url string `json:"clone_url"` + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Created_at string `json:"created_at"` + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Name string `json:"name"` // The name of the repository. + Description string `json:"description"` + Starred_at string `json:"starred_at,omitempty"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Allow_update_branch bool `json:"allow_update_branch,omitempty"` // Whether or not a pull request head branch that is behind its base branch can always be updated even if it is not required to be up to date before merging. + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + Git_url string `json:"git_url"` + Stargazers_url string `json:"stargazers_url"` + Master_branch string `json:"master_branch,omitempty"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Squash_merge_commit_message string `json:"squash_merge_commit_message,omitempty"` // The default value for a squash merge commit message: - `PR_BODY` - default to the pull request's body. - `COMMIT_MESSAGES` - default to the branch's commit messages. - `BLANK` - default to a blank commit message. + Subscription_url string `json:"subscription_url"` + Open_issues int `json:"open_issues"` + Compare_url string `json:"compare_url"` + Private bool `json:"private"` // Whether the repository is private or public. + Labels_url string `json:"labels_url"` + Homepage string `json:"homepage"` + Node_id string `json:"node_id"` + Html_url string `json:"html_url"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Git_refs_url string `json:"git_refs_url"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Has_pages bool `json:"has_pages"` + Deployments_url string `json:"deployments_url"` + Commits_url string `json:"commits_url"` + Assignees_url string `json:"assignees_url"` + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Collaborators_url string `json:"collaborators_url"` + Merges_url string `json:"merges_url"` + Branches_url string `json:"branches_url"` + Events_url string `json:"events_url"` + Git_tags_url string `json:"git_tags_url"` + Issue_comment_url string `json:"issue_comment_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Pushed_at string `json:"pushed_at"` + Merge_commit_title string `json:"merge_commit_title,omitempty"` // The default value for a merge commit title. - `PR_TITLE` - default to the pull request's title. - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name). + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Subscribers_url string `json:"subscribers_url"` + Languages_url string `json:"languages_url"` + Id int64 `json:"id"` // Unique identifier of the repository + Watchers_count int `json:"watchers_count"` + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` // Whether a squash merge commit can use the pull request title as default. **This property is closing down. Please use `squash_merge_commit_title` instead. + Archive_url string `json:"archive_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Forks int `json:"forks"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alert map[string]interface{} `json:"alert"` // The security alert of the vulnerable dependency. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project Webhooksproject `json:"project"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// Package represents the Package schema from the OpenAPI specification +type Package struct { + Created_at string `json:"created_at"` + Repository GeneratedType `json:"repository,omitempty"` // Minimal Repository + Package_type string `json:"package_type"` + Version_count int `json:"version_count"` // The number of versions of the package. + Html_url string `json:"html_url"` + Id int `json:"id"` // Unique identifier of the package. + Name string `json:"name"` // The name of the package. + Updated_at string `json:"updated_at"` + Visibility string `json:"visibility"` + Owner GeneratedType `json:"owner,omitempty"` // A GitHub user. + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit map[string]interface{} `json:"commit"` + Committer GeneratedType `json:"committer"` // Metaproperties for Git author/committer information. + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Parents []map[string]interface{} `json:"parents"` + Score float64 `json:"score"` + Sha string `json:"sha"` + Author GeneratedType `json:"author"` // A GitHub user. + Repository GeneratedType `json:"repository"` // Minimal Repository + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Url string `json:"url"` + Comments_url string `json:"comments_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action,omitempty"` + Check_run GeneratedType `json:"check_run"` // A check performed on the code of a given code change + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Issues string `json:"issues,omitempty"` // The level of permission to grant the access token for issues and related comments, assignees, labels, and milestones. + Organization_secrets string `json:"organization_secrets,omitempty"` // The level of permission to grant the access token to manage organization secrets. + Pages string `json:"pages,omitempty"` // The level of permission to grant the access token to retrieve Pages statuses, configuration, and builds, as well as create new builds. + Repository_projects string `json:"repository_projects,omitempty"` // The level of permission to grant the access token to manage repository projects, columns, and cards. + Organization_packages string `json:"organization_packages,omitempty"` // The level of permission to grant the access token for organization packages published to GitHub Packages. + Environments string `json:"environments,omitempty"` // The level of permission to grant the access token for managing repository environments. + Secrets string `json:"secrets,omitempty"` // The level of permission to grant the access token to manage repository secrets. + Organization_personal_access_tokens string `json:"organization_personal_access_tokens,omitempty"` // The level of permission to grant the access token for viewing and managing fine-grained personal access token requests to an organization. + Secret_scanning_alerts string `json:"secret_scanning_alerts,omitempty"` // The level of permission to grant the access token to view and manage secret scanning alerts. + Email_addresses string `json:"email_addresses,omitempty"` // The level of permission to grant the access token to manage the email addresses belonging to a user. + Organization_projects string `json:"organization_projects,omitempty"` // The level of permission to grant the access token to manage organization projects and projects public preview (where available). + Repository_hooks string `json:"repository_hooks,omitempty"` // The level of permission to grant the access token to manage the post-receive hooks for a repository. + Organization_custom_roles string `json:"organization_custom_roles,omitempty"` // The level of permission to grant the access token for custom repository roles management. + Organization_plan string `json:"organization_plan,omitempty"` // The level of permission to grant the access token for viewing an organization's plan. + Followers string `json:"followers,omitempty"` // The level of permission to grant the access token to manage the followers belonging to a user. + Statuses string `json:"statuses,omitempty"` // The level of permission to grant the access token for commit statuses. + Checks string `json:"checks,omitempty"` // The level of permission to grant the access token for checks on code. + Actions string `json:"actions,omitempty"` // The level of permission to grant the access token for GitHub Actions workflows, workflow runs, and artifacts. + Security_events string `json:"security_events,omitempty"` // The level of permission to grant the access token to view and manage security events like code scanning alerts. + Organization_administration string `json:"organization_administration,omitempty"` // The level of permission to grant the access token to manage access to an organization. + Organization_copilot_seat_management string `json:"organization_copilot_seat_management,omitempty"` // The level of permission to grant the access token for managing access to GitHub Copilot for members of an organization with a Copilot Business subscription. This property is in public preview and is subject to change. + Workflows string `json:"workflows,omitempty"` // The level of permission to grant the access token to update GitHub Actions workflow files. + Gpg_keys string `json:"gpg_keys,omitempty"` // The level of permission to grant the access token to view and manage GPG keys belonging to a user. + Team_discussions string `json:"team_discussions,omitempty"` // The level of permission to grant the access token to manage team discussions and related comments. + Organization_events string `json:"organization_events,omitempty"` // The level of permission to grant the access token to view events triggered by an activity in an organization. + Repository_custom_properties string `json:"repository_custom_properties,omitempty"` // The level of permission to grant the access token to view and edit custom properties for a repository, when allowed by the property. + Git_ssh_keys string `json:"git_ssh_keys,omitempty"` // The level of permission to grant the access token to manage git SSH keys. + Dependabot_secrets string `json:"dependabot_secrets,omitempty"` // The level of permission to grant the access token to manage Dependabot secrets. + Members string `json:"members,omitempty"` // The level of permission to grant the access token for organization teams and members. + Packages string `json:"packages,omitempty"` // The level of permission to grant the access token for packages published to GitHub Packages. + Vulnerability_alerts string `json:"vulnerability_alerts,omitempty"` // The level of permission to grant the access token to manage Dependabot alerts. + Codespaces string `json:"codespaces,omitempty"` // The level of permission to grant the access token to create, edit, delete, and list Codespaces. + Organization_custom_org_roles string `json:"organization_custom_org_roles,omitempty"` // The level of permission to grant the access token for custom organization roles management. + Contents string `json:"contents,omitempty"` // The level of permission to grant the access token for repository contents, commits, branches, downloads, releases, and merges. + Organization_personal_access_token_requests string `json:"organization_personal_access_token_requests,omitempty"` // The level of permission to grant the access token for viewing and managing fine-grained personal access tokens that have been approved by an organization. + Starring string `json:"starring,omitempty"` // The level of permission to grant the access token to list and manage repositories a user is starring. + Profile string `json:"profile,omitempty"` // The level of permission to grant the access token to manage the profile settings belonging to a user. + Metadata string `json:"metadata,omitempty"` // The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata. + Interaction_limits string `json:"interaction_limits,omitempty"` // The level of permission to grant the access token to view and manage interaction limits on a repository. + Single_file string `json:"single_file,omitempty"` // The level of permission to grant the access token to manage just a single file. + Organization_user_blocking string `json:"organization_user_blocking,omitempty"` // The level of permission to grant the access token to view and manage users blocked by the organization. + Deployments string `json:"deployments,omitempty"` // The level of permission to grant the access token for deployments and deployment statuses. + Organization_hooks string `json:"organization_hooks,omitempty"` // The level of permission to grant the access token to manage the post-receive hooks for an organization. + Organization_announcement_banners string `json:"organization_announcement_banners,omitempty"` // The level of permission to grant the access token to view and manage announcement banners for an organization. + Organization_custom_properties string `json:"organization_custom_properties,omitempty"` // The level of permission to grant the access token for custom property management. + Organization_self_hosted_runners string `json:"organization_self_hosted_runners,omitempty"` // The level of permission to grant the access token to view and manage GitHub Actions self-hosted runners available to an organization. + Pull_requests string `json:"pull_requests,omitempty"` // The level of permission to grant the access token for pull requests and related comments, assignees, labels, milestones, and merges. + Administration string `json:"administration,omitempty"` // The level of permission to grant the access token for repository creation, deletion, settings, teams, and collaborators creation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository map[string]interface{} `json:"repository,omitempty"` // A git repository + Sender GeneratedType `json:"sender"` // A GitHub user. + Team Webhooksteam1 `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Target_url string `json:"target_url"` // Closing down notice: the URL to associate with this status. + Id int64 `json:"id"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Environment string `json:"environment,omitempty"` // The environment of the deployment that the status is for. + Log_url string `json:"log_url,omitempty"` // The URL to associate with this status. + Creator GeneratedType `json:"creator"` // A GitHub user. + Repository_url string `json:"repository_url"` + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` + State string `json:"state"` // The state of the status. + Description string `json:"description"` // A short description of the status. + Environment_url string `json:"environment_url,omitempty"` // The URL for accessing your environment. + Url string `json:"url"` + Deployment_url string `json:"deployment_url"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Member Webhooksuser `json:"member"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// Traffic represents the Traffic schema from the OpenAPI specification +type Traffic struct { + Count int `json:"count"` + Timestamp string `json:"timestamp"` + Uniques int `json:"uniques"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Body string `json:"body"` // The comment text. + Created_at string `json:"created_at"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + User GeneratedType `json:"user"` // A GitHub user. + Author_association string `json:"author_association"` // How the author is associated with the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation Installation `json:"installation"` // Installation + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories []map[string]interface{} `json:"repositories,omitempty"` // An array of repository objects that the installation can access. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Requester interface{} `json:"requester,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Label Webhookslabel `json:"label"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + All []int `json:"all"` + Owner []int `json:"owner"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` // The date and time at which the variable was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Name string `json:"name"` // The name of the variable. + Selected_repositories_url string `json:"selected_repositories_url,omitempty"` + Updated_at string `json:"updated_at"` // The date and time at which the variable was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Value string `json:"value"` // The value of the variable. + Visibility string `json:"visibility"` // Visibility of a variable +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2 GeneratedType `json:"projects_v2"` // A projects v2 project +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + User GeneratedType `json:"user"` // Collaborator + Permission string `json:"permission"` + Role_name string `json:"role_name"` +} + +// Workflow represents the Workflow schema from the OpenAPI specification +type Workflow struct { + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Name string `json:"name"` + State string `json:"state"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Path string `json:"path"` + Deleted_at string `json:"deleted_at,omitempty"` + Html_url string `json:"html_url"` + Badge_url string `json:"badge_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue2 `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commits_url string `json:"commits_url"` + Watchers_count int `json:"watchers_count"` + Contributors_url string `json:"contributors_url"` + Forks int `json:"forks"` + Clone_url string `json:"clone_url"` + Homepage string `json:"homepage"` + Forks_url string `json:"forks_url"` + Master_branch string `json:"master_branch,omitempty"` + Stargazers_url string `json:"stargazers_url"` + Updated_at string `json:"updated_at"` + Git_commits_url string `json:"git_commits_url"` + Contents_url string `json:"contents_url"` + Stargazers_count int `json:"stargazers_count"` + Subscription_url string `json:"subscription_url"` + Language string `json:"language"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Events_url string `json:"events_url"` + License GeneratedType `json:"license"` // License Simple + Mirror_url string `json:"mirror_url"` + Node_id string `json:"node_id"` + Languages_url string `json:"languages_url"` + Issue_events_url string `json:"issue_events_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Deployments_url string `json:"deployments_url"` + Git_url string `json:"git_url"` + Merges_url string `json:"merges_url"` + Full_name string `json:"full_name"` + Pulls_url string `json:"pulls_url"` + Downloads_url string `json:"downloads_url"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Tags_url string `json:"tags_url"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Network_count int `json:"network_count,omitempty"` + Collaborators_url string `json:"collaborators_url"` + Releases_url string `json:"releases_url"` + Archive_url string `json:"archive_url"` + Html_url string `json:"html_url"` + Keys_url string `json:"keys_url"` + Trees_url string `json:"trees_url"` + Size int `json:"size"` + Pushed_at string `json:"pushed_at"` + Milestones_url string `json:"milestones_url"` + Topics []string `json:"topics,omitempty"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Fork bool `json:"fork"` + Ssh_url string `json:"ssh_url"` + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Compare_url string `json:"compare_url"` + Git_tags_url string `json:"git_tags_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Description string `json:"description"` + Issues_url string `json:"issues_url"` + Blobs_url string `json:"blobs_url"` + Svn_url string `json:"svn_url"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Comments_url string `json:"comments_url"` + Labels_url string `json:"labels_url"` + Name string `json:"name"` // The name of the repository. + Subscribers_url string `json:"subscribers_url"` + Statuses_url string `json:"statuses_url"` + Git_refs_url string `json:"git_refs_url"` + Id int `json:"id"` // Unique identifier of the repository + Url string `json:"url"` + Watchers int `json:"watchers"` + Has_pages bool `json:"has_pages"` + Role_name string `json:"role_name,omitempty"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Issue_comment_url string `json:"issue_comment_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Assignees_url string `json:"assignees_url"` + Created_at string `json:"created_at"` + Notifications_url string `json:"notifications_url"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Teams_url string `json:"teams_url"` + Branches_url string `json:"branches_url"` + Forks_count int `json:"forks_count"` + Private bool `json:"private"` // Whether the repository is private or public. + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Open_issues int `json:"open_issues"` + Hooks_url string `json:"hooks_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Open_issues_count int `json:"open_issues_count"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Domains []string `json:"domains"` // Array of the domain set and its alternate name (if it is configured) + Expires_at string `json:"expires_at,omitempty"` + State string `json:"state"` + Description string `json:"description"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Version_id int `json:"version_id"` // The ID of the previous version of the ruleset + Actor map[string]interface{} `json:"actor"` // The actor who updated the ruleset + State map[string]interface{} `json:"state"` // The state of the ruleset version +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Security_advisory Webhookssecurityadvisory `json:"security_advisory"` // The details of the security advisory, including summary, description, and severity. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Invite_link string `json:"invite_link"` // The link that a student can use to accept the assignment. + Max_members int `json:"max_members"` // The maximum allowable members per team. + TypeField string `json:"type"` // Whether it's a group assignment or individual assignment. + Students_are_repo_admins bool `json:"students_are_repo_admins"` // Whether students are admins on created repository when a student accepts the assignment. + Invitations_enabled bool `json:"invitations_enabled"` // Whether the invitation link is enabled. Visiting an enabled invitation link will accept the assignment. + Submitted int `json:"submitted"` // The number of students that have submitted the assignment. + Feedback_pull_requests_enabled bool `json:"feedback_pull_requests_enabled"` // Whether feedback pull request will be created when a student accepts the assignment. + Accepted int `json:"accepted"` // The number of students that have accepted the assignment. + Deadline string `json:"deadline"` // The time at which the assignment is due. + Language string `json:"language"` // The programming language used in the assignment. + Max_teams int `json:"max_teams"` // The maximum allowable teams for the assignment. + Editor string `json:"editor"` // The selected editor for the assignment. + Public_repo bool `json:"public_repo"` // Whether an accepted assignment creates a public repository. + Classroom Classroom `json:"classroom"` // A GitHub Classroom classroom + Starter_code_repository GeneratedType `json:"starter_code_repository"` // A GitHub repository view for Classroom + Title string `json:"title"` // Assignment title. + Slug string `json:"slug"` // Sluggified name of the assignment. + Passing int `json:"passing"` // The number of students that have passed the assignment. + Id int `json:"id"` // Unique identifier of the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Used int `json:"used"` + Limit int `json:"limit"` + Remaining int `json:"remaining"` + Reset int `json:"reset"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Issue interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) the comment belongs to. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Comment Webhooksissuecomment `json:"comment"` // The [comment](https://docs.github.com/rest/issues/comments#get-an-issue-comment) itself. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Usageitems []map[string]interface{} `json:"usageItems,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Head_ref string `json:"head_ref"` // The full ref of the merge group. + Head_sha string `json:"head_sha"` // The SHA of the merge group. + Base_ref string `json:"base_ref"` // The full ref of the branch the merge group will be merged into. + Base_sha string `json:"base_sha"` // The SHA of the merge group's parent commit. + Head_commit GeneratedType `json:"head_commit"` // A commit. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Title string `json:"title"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow Webhooksworkflow `json:"workflow"` + Workflow_run map[string]interface{} `json:"workflow_run"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Apps_url string `json:"apps_url"` + Teams []map[string]interface{} `json:"teams"` + Teams_url string `json:"teams_url"` + Url string `json:"url"` + Users []map[string]interface{} `json:"users"` + Users_url string `json:"users_url"` + Apps []map[string]interface{} `json:"apps"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dismissal_commit_id string `json:"dismissal_commit_id,omitempty"` + Dismissal_message string `json:"dismissal_message"` + Review_id int `json:"review_id"` + State string `json:"state"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_id string `json:"commit_id"` + Id int `json:"id"` + Lock_reason string `json:"lock_reason"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Created_at string `json:"created_at"` + Commit_url string `json:"commit_url"` + Event string `json:"event"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Membership Webhooksmembership `json:"membership"` // The membership between the user and the organization. Not present when the action is `member_invited`. + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit map[string]interface{} `json:"commit"` + Name string `json:"name"` + Protected bool `json:"protected"` + Protection GeneratedType `json:"protection,omitempty"` // Branch Protection + Protection_url string `json:"protection_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Started_at string `json:"started_at"` // The start time of an autofix in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Status string `json:"status"` // The status of an autofix. + Description string `json:"description"` // The description of an autofix. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Role string `json:"role"` // The role of the user in the team. + State string `json:"state"` // The state of the user's membership in the team. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Assigner GeneratedType `json:"assigner"` // A GitHub user. + Created_at string `json:"created_at"` + Id int `json:"id"` + Url string `json:"url"` + Commit_id string `json:"commit_id"` + Commit_url string `json:"commit_url"` + Event string `json:"event"` + Node_id string `json:"node_id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Event string `json:"event,omitempty"` + Node_id string `json:"node_id"` + Parents []map[string]interface{} `json:"parents"` + Url string `json:"url"` + Verification map[string]interface{} `json:"verification"` + Committer map[string]interface{} `json:"committer"` // Identifying information for the git-user + Html_url string `json:"html_url"` + Message string `json:"message"` // Message describing the purpose of the commit + Sha string `json:"sha"` // SHA for the commit + Author map[string]interface{} `json:"author"` // Identifying information for the git-user + Tree map[string]interface{} `json:"tree"` +} + +// Webhooksworkflowjobrun represents the Webhooksworkflowjobrun schema from the OpenAPI specification +type Webhooksworkflowjobrun struct { + Status string `json:"status"` + Updated_at string `json:"updated_at"` + Conclusion interface{} `json:"conclusion"` + Created_at string `json:"created_at"` + Environment string `json:"environment"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Name interface{} `json:"name"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Rate GeneratedType `json:"rate"` + Resources map[string]interface{} `json:"resources"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Milestone Milestone `json:"milestone,omitempty"` // A collection of related issues and pull requests. + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request Webhookspullrequest5 `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Push_protection_bypassed_by GeneratedType `json:"push_protection_bypassed_by,omitempty"` // A GitHub user. + Resolved_at string `json:"resolved_at,omitempty"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Push_protection_bypass_request_reviewer_comment string `json:"push_protection_bypass_request_reviewer_comment,omitempty"` // An optional comment when reviewing a push protection bypass. + Resolution string `json:"resolution,omitempty"` // **Required when the `state` is `resolved`.** The reason for resolving the alert. + Secret_type string `json:"secret_type,omitempty"` // The type of secret that secret scanning detected. + Has_more_locations bool `json:"has_more_locations,omitempty"` // A boolean value representing whether or not the token in the alert was detected in more than one location. + Resolution_comment string `json:"resolution_comment,omitempty"` // An optional comment to resolve an alert. + First_location_detected GeneratedType `json:"first_location_detected,omitempty"` // Details on the location where the token was initially detected. This can be a commit, wiki commit, issue, discussion, pull request. + Number int `json:"number,omitempty"` // The security alert number. + Locations_url string `json:"locations_url,omitempty"` // The REST API URL of the code locations for this alert. + Is_base64_encoded bool `json:"is_base64_encoded,omitempty"` // A boolean value representing whether or not alert is base64 encoded + Secret string `json:"secret,omitempty"` // The secret that was detected. + Push_protection_bypass_request_html_url string `json:"push_protection_bypass_request_html_url,omitempty"` // The URL to a push protection bypass request. + Push_protection_bypassed_at string `json:"push_protection_bypassed_at,omitempty"` // The time that push protection was bypassed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Url string `json:"url,omitempty"` // The REST API URL of the alert resource. + Push_protection_bypassed bool `json:"push_protection_bypassed,omitempty"` // Whether push protection was bypassed for the detected secret. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Push_protection_bypass_request_comment string `json:"push_protection_bypass_request_comment,omitempty"` // An optional comment when requesting a push protection bypass. + Resolved_by GeneratedType `json:"resolved_by,omitempty"` // A GitHub user. + Secret_type_display_name string `json:"secret_type_display_name,omitempty"` // User-friendly name for the detected secret, matching the `secret_type`. For a list of built-in patterns, see "[Supported secret scanning patterns](https://docs.github.com/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets)." + Html_url string `json:"html_url,omitempty"` // The GitHub URL of the alert resource. + Publicly_leaked bool `json:"publicly_leaked,omitempty"` // Whether the detected secret was publicly leaked. + Created_at string `json:"created_at,omitempty"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Multi_repo bool `json:"multi_repo,omitempty"` // Whether the detected secret was found in multiple repositories under the same organization or enterprise. + Push_protection_bypass_request_reviewer GeneratedType `json:"push_protection_bypass_request_reviewer,omitempty"` // A GitHub user. + State string `json:"state,omitempty"` // Sets the state of the secret scanning alert. You must provide `resolution` when you set the state to `resolved`. + Validity string `json:"validity,omitempty"` // The token status as of the latest validity check. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Image_details GeneratedType `json:"image_details"` // Provides details of a hosted runner image + Machine_size_details GeneratedType `json:"machine_size_details"` // Provides details of a particular machine spec. + Platform string `json:"platform"` // The operating system of the image. + Status string `json:"status"` // The status of the runner. + Name string `json:"name"` // The name of the hosted runner. + Public_ip_enabled bool `json:"public_ip_enabled"` // Whether public IP is enabled for the hosted runners. + Id int `json:"id"` // The unique identifier of the hosted runner. + Maximum_runners int `json:"maximum_runners,omitempty"` // The maximum amount of hosted runners. Runners will not scale automatically above this number. Use this setting to limit your cost. + Public_ips []GeneratedType `json:"public_ips,omitempty"` // The public IP ranges when public IP is enabled for the hosted runners. + Runner_group_id int `json:"runner_group_id,omitempty"` // The unique identifier of the group that the hosted runner belongs to. + Last_active_on string `json:"last_active_on,omitempty"` // The time at which the runner was last used, in ISO 8601 format. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Title string `json:"title"` + Repository_url string `json:"repository_url"` + State_reason string `json:"state_reason,omitempty"` + Labels []map[string]interface{} `json:"labels"` + Draft bool `json:"draft,omitempty"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Comments int `json:"comments"` + Url string `json:"url"` + Repository Repository `json:"repository,omitempty"` // A repository on GitHub. + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Id int64 `json:"id"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Reactions GeneratedType `json:"reactions,omitempty"` + Labels_url string `json:"labels_url"` + Body_text string `json:"body_text,omitempty"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Created_at string `json:"created_at"` + Timeline_url string `json:"timeline_url,omitempty"` + Body_html string `json:"body_html,omitempty"` + Score float64 `json:"score"` + Body string `json:"body,omitempty"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Closed_at string `json:"closed_at"` + Html_url string `json:"html_url"` + Number int `json:"number"` + Events_url string `json:"events_url"` + Updated_at string `json:"updated_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + State string `json:"state"` + Comments_url string `json:"comments_url"` + Sub_issues_summary map[string]interface{} `json:"sub_issues_summary,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Locked bool `json:"locked"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Key string `json:"key"` + Title string `json:"title"` + Created_at string `json:"created_at"` + Id int `json:"id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow_job interface{} `json:"workflow_job"` + Action string `json:"action"` + Deployment Deployment `json:"deployment,omitempty"` // A request for a specific ref(branch,sha,tag) to be deployed + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// Release represents the Release schema from the OpenAPI specification +type Release struct { + Name string `json:"name"` + Prerelease bool `json:"prerelease"` // Whether to identify the release as a prerelease or a full release. + Assets []GeneratedType `json:"assets"` + Body string `json:"body,omitempty"` + Body_html string `json:"body_html,omitempty"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Author GeneratedType `json:"author"` // A GitHub user. + Discussion_url string `json:"discussion_url,omitempty"` // The URL of the release discussion. + Reactions GeneratedType `json:"reactions,omitempty"` + Url string `json:"url"` + Zipball_url string `json:"zipball_url"` + Tarball_url string `json:"tarball_url"` + Upload_url string `json:"upload_url"` + Body_text string `json:"body_text,omitempty"` + Draft bool `json:"draft"` // true to create a draft (unpublished) release, false to create a published one. + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Assets_url string `json:"assets_url"` + Published_at string `json:"published_at"` + Tag_name string `json:"tag_name"` // The name of the tag. + Target_commitish string `json:"target_commitish"` // Specifies the commitish value that determines where the Git tag is created from. + Mentions_count int `json:"mentions_count,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Total int `json:"total"` + Week int `json:"week"` + Days []int `json:"days"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Documentation_url string `json:"documentation_url"` + Errors []map[string]interface{} `json:"errors,omitempty"` + Message string `json:"message"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Blocked_user Webhooksuser `json:"blocked_user"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Draft bool `json:"draft,omitempty"` // Indicates whether or not the pull request is a draft. + Merged bool `json:"merged"` + Labels []map[string]interface{} `json:"labels"` + Body string `json:"body"` + Changed_files int `json:"changed_files"` + Comments int `json:"comments"` + Mergeable_state string `json:"mergeable_state"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Requested_teams []GeneratedType `json:"requested_teams,omitempty"` + Url string `json:"url"` + Rebaseable bool `json:"rebaseable,omitempty"` + Commits int `json:"commits"` + Merged_at string `json:"merged_at"` + Mergeable bool `json:"mergeable"` + Id int64 `json:"id"` + Issue_url string `json:"issue_url"` + Additions int `json:"additions"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Closed_at string `json:"closed_at"` + Links map[string]interface{} `json:"_links"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Review_comments_url string `json:"review_comments_url"` + Created_at string `json:"created_at"` + Commits_url string `json:"commits_url"` + Comments_url string `json:"comments_url"` + Number int `json:"number"` // Number uniquely identifying the pull request within its repository. + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Requested_reviewers []GeneratedType `json:"requested_reviewers,omitempty"` + State string `json:"state"` // State of this Pull Request. Either `open` or `closed`. + User GeneratedType `json:"user"` // A GitHub user. + Merge_commit_sha string `json:"merge_commit_sha"` + Base map[string]interface{} `json:"base"` + Patch_url string `json:"patch_url"` + Merged_by GeneratedType `json:"merged_by"` // A GitHub user. + Statuses_url string `json:"statuses_url"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Review_comment_url string `json:"review_comment_url"` + Auto_merge GeneratedType `json:"auto_merge"` // The status of auto merging a pull request. + Deletions int `json:"deletions"` + Maintainer_can_modify bool `json:"maintainer_can_modify"` // Indicates whether maintainers can modify the pull request. + Head map[string]interface{} `json:"head"` + Locked bool `json:"locked"` + Title string `json:"title"` // The title of the pull request. + Html_url string `json:"html_url"` + Diff_url string `json:"diff_url"` + Review_comments int `json:"review_comments"` + Updated_at string `json:"updated_at"` +} + +// Link represents the Link schema from the OpenAPI specification +type Link struct { + Href string `json:"href"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Body string `json:"body"` // The generated body describing the contents of the release supporting markdown formatting + Name string `json:"name"` // The generated name of the release +} + +// Authorization represents the Authorization schema from the OpenAPI specification +type Authorization struct { + Id int64 `json:"id"` + Token string `json:"token"` + Note string `json:"note"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + App map[string]interface{} `json:"app"` + Hashed_token string `json:"hashed_token"` + Installation GeneratedType `json:"installation,omitempty"` + Note_url string `json:"note_url"` + Expires_at string `json:"expires_at"` + User GeneratedType `json:"user,omitempty"` // A GitHub user. + Fingerprint string `json:"fingerprint"` + Token_last_eight string `json:"token_last_eight"` + Scopes []string `json:"scopes"` // A list of scopes that this authorization is in. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Teams []Team `json:"teams"` + Users []GeneratedType `json:"users"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Plan_type string `json:"plan_type,omitempty"` // The Copilot plan of the organization, or the parent enterprise, when applicable. + Last_activity_at string `json:"last_activity_at,omitempty"` // Timestamp of user's last GitHub Copilot activity, in ISO 8601 format. + Last_activity_editor string `json:"last_activity_editor,omitempty"` // Last editor that was used by the user for a GitHub Copilot completion. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. + Assignee GeneratedType `json:"assignee,omitempty"` // A GitHub user. + Created_at string `json:"created_at"` // Timestamp of when the assignee was last granted access to GitHub Copilot, in ISO 8601 format. + Pending_cancellation_date string `json:"pending_cancellation_date,omitempty"` // The pending cancellation date for the seat, in `YYYY-MM-DD` format. This will be null unless the assignee's Copilot access has been canceled during the current billing cycle. If the seat has been cancelled, this corresponds to the start of the organization's next billing cycle. + Updated_at string `json:"updated_at,omitempty"` // **Closing down notice:** This field is no longer relevant and is closing down. Use the `created_at` field to determine when the assignee was last granted access to GitHub Copilot. Timestamp of when the assignee's GitHub Copilot access was last updated, in ISO 8601 format. + Assigning_team interface{} `json:"assigning_team,omitempty"` // The team through which the assignee is granted access to GitHub Copilot, if applicable. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + File_patterns []string `json:"file_patterns"` // Array of file patterns. Pull requests which change matching files must be approved by the specified team. File patterns use the same syntax as `.gitignore` files. + Minimum_approvals int `json:"minimum_approvals"` // Minimum number of approvals required from the specified team. If set to zero, the team will be added to the pull request but approval is optional. + Reviewer GeneratedType `json:"reviewer"` // A required reviewing team +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Rule Webhooksrule `json:"rule"` // The branch protection rule. Includes a `name` and all the [branch protection settings](https://docs.github.com/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#about-branch-protection-settings) applied to branches that match the name. Binary settings are boolean. Multi-level configurations are one of `off`, `non_admins`, or `everyone`. Actor and build lists are arrays of strings. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Active_caches_count int `json:"active_caches_count"` // The number of active caches in the repository. + Active_caches_size_in_bytes int `json:"active_caches_size_in_bytes"` // The sum of the size in bytes of all the active cache items in the repository. + Full_name string `json:"full_name"` // The repository owner and name for the cache usage being shown. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2 GeneratedType `json:"projects_v2"` // A projects v2 project + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// Webhooksreviewcomment represents the Webhooksreviewcomment schema from the OpenAPI specification +type Webhooksreviewcomment struct { + Html_url string `json:"html_url"` // HTML URL for the pull request review comment. + Start_side string `json:"start_side"` // The side of the first line of the range for a multi-line comment. + In_reply_to_id int `json:"in_reply_to_id,omitempty"` // The comment ID to reply to. + Original_position int `json:"original_position"` // The index of the original line in the diff to which the comment applies. + Pull_request_review_id int `json:"pull_request_review_id"` // The ID of the pull request review to which the comment belongs. + Updated_at string `json:"updated_at"` + Commit_id string `json:"commit_id"` // The SHA of the commit to which the comment applies. + Original_start_line int `json:"original_start_line"` // The first line of the range for a multi-line comment. + Links map[string]interface{} `json:"_links"` + Path string `json:"path"` // The relative path of the file to which the comment applies. + Side string `json:"side"` // The side of the first line of the range for a multi-line comment. + Start_line int `json:"start_line"` // The first line of the range for a multi-line comment. + Position int `json:"position"` // The line index in the diff to which the comment applies. + Subject_type string `json:"subject_type,omitempty"` // The level at which the comment is targeted, can be a diff line or a file. + Id int `json:"id"` // The ID of the pull request review comment. + Node_id string `json:"node_id"` // The node ID of the pull request review comment. + Reactions map[string]interface{} `json:"reactions"` + Original_commit_id string `json:"original_commit_id"` // The SHA of the original commit to which the comment applies. + Body string `json:"body"` // The text of the comment. + User map[string]interface{} `json:"user"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Diff_hunk string `json:"diff_hunk"` // The diff of the line that the comment refers to. + Pull_request_url string `json:"pull_request_url"` // URL for the pull request that the review comment belongs to. + Created_at string `json:"created_at"` + Line int `json:"line"` // The line of the blob to which the comment applies. The last line of the range for a multi-line comment + Original_line int `json:"original_line"` // The line of the blob to which the comment applies. The last line of the range for a multi-line comment + Url string `json:"url"` // URL for the pull request review comment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) the comment belongs to. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Comment map[string]interface{} `json:"comment"` // The [comment](https://docs.github.com/rest/issues/comments#get-an-issue-comment) itself. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enabled_by GeneratedType `json:"enabled_by"` // A GitHub user. + Merge_method string `json:"merge_method"` // The merge method to use. + Commit_message string `json:"commit_message"` // Commit message for the merge commit. + Commit_title string `json:"commit_title"` // Title for the merge commit message. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes"` // The changes to the comment if the action was `edited`. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Pull_request GeneratedType `json:"pull_request"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Number int `json:"number"` // The pull request number. + Action string `json:"action"` + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Previous_marketplace_purchase Webhookspreviousmarketplacepurchase `json:"previous_marketplace_purchase,omitempty"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Action string `json:"action"` + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Effective_date string `json:"effective_date"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the network settings resource. + Network_configuration_id string `json:"network_configuration_id,omitempty"` // The identifier of the network configuration that is using this settings resource. + Region string `json:"region"` // The location of the subnet this network settings resource is configured for. + Subnet_id string `json:"subnet_id"` // The subnet this network settings resource is configured for. + Id string `json:"id"` // The unique identifier of the network settings resource. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Issue_url string `json:"issue_url"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` // URL for the issue comment + Author_association string `json:"author_association"` // How the author is associated with the repository. + Body_html string `json:"body_html,omitempty"` + Html_url string `json:"html_url"` + Id int64 `json:"id"` // Unique identifier of the issue comment + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Body string `json:"body,omitempty"` // Contents of the issue comment + Body_text string `json:"body_text,omitempty"` + Node_id string `json:"node_id"` + Reactions GeneratedType `json:"reactions,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. +} + +// Webhooksissuecomment represents the Webhooksissuecomment schema from the OpenAPI specification +type Webhooksissuecomment struct { + Issue_url string `json:"issue_url"` + Performed_via_github_app Integration `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Updated_at string `json:"updated_at"` + Url string `json:"url"` // URL for the issue comment + Body string `json:"body"` // Contents of the issue comment + Created_at string `json:"created_at"` + Id int64 `json:"id"` // Unique identifier of the issue comment + Node_id string `json:"node_id"` + Reactions map[string]interface{} `json:"reactions"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Html_url string `json:"html_url"` + User map[string]interface{} `json:"user"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Ref string `json:"ref"` // The Git reference of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Commit_oid string `json:"commit_oid"` // The commit SHA of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Sponsorship Webhookssponsorship `json:"sponsorship"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Git_status map[string]interface{} `json:"git_status"` // Details about the codespace's git repository. + Created_at string `json:"created_at"` + Retention_expires_at string `json:"retention_expires_at,omitempty"` // When a codespace will be auto-deleted based on the "retention_period_minutes" and "last_used_at" + Pending_operation bool `json:"pending_operation,omitempty"` // Whether or not a codespace has a pending async operation. This would mean that the codespace is temporarily unavailable. The only thing that you can do with a codespace in this state is delete it. + Environment_id string `json:"environment_id"` // UUID identifying this codespace's environment. + Id int64 `json:"id"` + Idle_timeout_notice string `json:"idle_timeout_notice,omitempty"` // Text to show user when codespace idle timeout minutes has been overriden by an organization policy + Name string `json:"name"` // Automatically generated name of this codespace. + Machine GeneratedType `json:"machine"` // A description of the machine powering a codespace. + Repository GeneratedType `json:"repository"` // Full Repository + Url string `json:"url"` // API URL for this codespace. + Prebuild bool `json:"prebuild"` // Whether the codespace was created from a prebuild. + Runtime_constraints map[string]interface{} `json:"runtime_constraints,omitempty"` + Billable_owner GeneratedType `json:"billable_owner"` // A GitHub user. + Web_url string `json:"web_url"` // URL to access this codespace on the web. + Last_used_at string `json:"last_used_at"` // Last known time this codespace was started. + Retention_period_minutes int `json:"retention_period_minutes,omitempty"` // Duration in minutes after codespace has gone idle in which it will be deleted. Must be integer minutes between 0 and 43200 (30 days). + Publish_url string `json:"publish_url,omitempty"` // API URL to publish this codespace to a new repository. + State string `json:"state"` // State of this codespace. + Stop_url string `json:"stop_url"` // API URL to stop this codespace. + Devcontainer_path string `json:"devcontainer_path,omitempty"` // Path to devcontainer.json from repo root used to create Codespace. + Pending_operation_disabled_reason string `json:"pending_operation_disabled_reason,omitempty"` // Text to show user when codespace is disabled by a pending operation + Machines_url string `json:"machines_url"` // API URL to access available alternate machine types for this codespace. + Pulls_url string `json:"pulls_url"` // API URL for the Pull Request associated with this codespace, if any. + Display_name string `json:"display_name,omitempty"` // Display name for this codespace. + Location string `json:"location"` // The initally assigned location of a new codespace. + Owner GeneratedType `json:"owner"` // A GitHub user. + Idle_timeout_minutes int `json:"idle_timeout_minutes"` // The number of minutes of inactivity after which this codespace will be automatically stopped. + Start_url string `json:"start_url"` // API URL to start this codespace. + Updated_at string `json:"updated_at"` + Recent_folders []string `json:"recent_folders"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Label Webhookslabel `json:"label,omitempty"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Changes map[string]interface{} `json:"changes"` // The changes to the issue. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// Webhookscomment represents the Webhookscomment schema from the OpenAPI specification +type Webhookscomment struct { + Updated_at string `json:"updated_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Id int `json:"id"` + Reactions map[string]interface{} `json:"reactions"` + Repository_url string `json:"repository_url"` + Body string `json:"body"` + Discussion_id int `json:"discussion_id"` + Node_id string `json:"node_id"` + Parent_id int `json:"parent_id"` + Child_comment_count int `json:"child_comment_count"` + Html_url string `json:"html_url"` + User map[string]interface{} `json:"user"` + Created_at string `json:"created_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Definition map[string]interface{} `json:"definition"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Visibility string `json:"visibility"` // Visibility of a secret + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. + Selected_repositories_url string `json:"selected_repositories_url,omitempty"` + Updated_at string `json:"updated_at"` +} + +// Webhooksprojectcard represents the Webhooksprojectcard schema from the OpenAPI specification +type Webhooksprojectcard struct { + Node_id string `json:"node_id"` + Column_id int `json:"column_id"` + Created_at string `json:"created_at"` + Note string `json:"note"` + Updated_at string `json:"updated_at"` + Content_url string `json:"content_url,omitempty"` + Id int `json:"id"` // The project card's ID + Project_url string `json:"project_url"` + After_id int `json:"after_id,omitempty"` + Column_url string `json:"column_url"` + Url string `json:"url"` + Archived bool `json:"archived"` // Whether or not the card is archived + Creator map[string]interface{} `json:"creator"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_requests []GeneratedType `json:"pull_requests"` // Pull requests that are open with a `head_sha` or `head_branch` that matches the check. The returned pull requests do not necessarily indicate pull requests that triggered the check. + Url string `json:"url"` + External_id string `json:"external_id"` + Started_at string `json:"started_at"` + App GeneratedType `json:"app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Check_suite map[string]interface{} `json:"check_suite"` + Details_url string `json:"details_url"` + Head_sha string `json:"head_sha"` // The SHA of the commit that is being checked. + Status string `json:"status"` // The phase of the lifecycle that the check is currently in. Statuses of waiting, requested, and pending are reserved for GitHub Actions check runs. + Conclusion string `json:"conclusion"` + Node_id string `json:"node_id"` + Completed_at string `json:"completed_at"` + Html_url string `json:"html_url"` + Id int64 `json:"id"` // The id of the check. + Name string `json:"name"` // The name of the check. + Output map[string]interface{} `json:"output"` + Deployment GeneratedType `json:"deployment,omitempty"` // A deployment created as the result of an Actions check run from a workflow that references an environment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + TypeField GeneratedType `json:"type"` // The type of issue. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// Integration represents the Integration schema from the OpenAPI specification +type Integration struct { + Client_id string `json:"client_id,omitempty"` + Updated_at string `json:"updated_at"` + Html_url string `json:"html_url"` + Id int `json:"id"` // Unique identifier of the GitHub app + Name string `json:"name"` // The name of the GitHub app + Description string `json:"description"` + Node_id string `json:"node_id"` + Owner interface{} `json:"owner"` + Slug string `json:"slug,omitempty"` // The slug name of the GitHub app + Created_at string `json:"created_at"` + Events []string `json:"events"` // The list of events for the GitHub app. Note that the `installation_target`, `security_advisory`, and `meta` events are not included because they are global events and not specific to an installation. + External_url string `json:"external_url"` + Installations_count int `json:"installations_count,omitempty"` // The number of installations associated with the GitHub app. Only returned when the integration is requesting details about itself. + Permissions map[string]interface{} `json:"permissions"` // The set of permissions for the GitHub app +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Dismissed_comment string `json:"dismissed_comment,omitempty"` // The dismissal comment associated with the dismissal of the alert. + Dismissed_reason string `json:"dismissed_reason"` // **Required when the state is dismissed.** The reason for dismissing or closing the alert. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Instances_url string `json:"instances_url"` // The REST API URL for fetching the list of instances for an alert. + Fixed_at string `json:"fixed_at,omitempty"` // The time that the alert was no longer detected and was considered fixed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Most_recent_instance GeneratedType `json:"most_recent_instance"` + Tool GeneratedType `json:"tool"` + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissal_approved_by GeneratedType `json:"dismissal_approved_by,omitempty"` // A GitHub user. + Number int `json:"number"` // The security alert number. + Rule GeneratedType `json:"rule"` + State string `json:"state"` // State of a code scanning alert. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Url string `json:"url"` // The REST API URL of the alert resource. +} + +// Dependency represents the Dependency schema from the OpenAPI specification +type Dependency struct { + Relationship string `json:"relationship,omitempty"` // A notation of whether a dependency is requested directly by this manifest or is a dependency of another dependency. + Scope string `json:"scope,omitempty"` // A notation of whether the dependency is required for the primary build artifact (runtime) or is only used for development. Future versions of this specification may allow for more granular scopes. + Dependencies []string `json:"dependencies,omitempty"` // Array of package-url (PURLs) of direct child dependencies. + Metadata Metadata `json:"metadata,omitempty"` // User-defined metadata to store domain-specific information limited to 8 keys with scalar values. + Package_url string `json:"package_url,omitempty"` // Package-url (PURL) of dependency. See https://github.com/package-url/purl-spec for more details. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Url string `json:"url"` + Body string `json:"body,omitempty"` + Html_url string `json:"html_url"` + Key string `json:"key"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Build map[string]interface{} `json:"build"` // The [List GitHub Pages builds](https://docs.github.com/rest/pages/pages#list-github-pages-builds) itself. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Id int `json:"id"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Milestone Webhooksmilestone `json:"milestone"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_id map[string]interface{} `json:"repository_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Hooray int `json:"hooray"` + Total_count int `json:"total_count"` + Confused int `json:"confused"` + Heart int `json:"heart"` + Rocket int `json:"rocket"` + Url string `json:"url"` + Field1 int `json:"+1"` + Field1 int `json:"-1"` + Laugh int `json:"laugh"` + Eyes int `json:"eyes"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Repository_advisory GeneratedType `json:"repository_advisory"` // A repository security advisory. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// Contributor represents the Contributor schema from the OpenAPI specification +type Contributor struct { + Followers_url string `json:"followers_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Repos_url string `json:"repos_url,omitempty"` + Email string `json:"email,omitempty"` + Login string `json:"login,omitempty"` + Gists_url string `json:"gists_url,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + TypeField string `json:"type"` + Events_url string `json:"events_url,omitempty"` + Name string `json:"name,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + Contributions int `json:"contributions"` + Site_admin bool `json:"site_admin,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Id int `json:"id,omitempty"` + Url string `json:"url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Starred_url string `json:"starred_url,omitempty"` +} + +// Webhooksdeploykey represents the Webhooksdeploykey schema from the OpenAPI specification +type Webhooksdeploykey struct { + Last_used string `json:"last_used,omitempty"` + Id int `json:"id"` + Key string `json:"key"` + Read_only bool `json:"read_only"` + Verified bool `json:"verified"` + Created_at string `json:"created_at"` + Enabled bool `json:"enabled,omitempty"` + Title string `json:"title"` + Url string `json:"url"` + Added_by string `json:"added_by,omitempty"` +} + +// Page represents the Page schema from the OpenAPI specification +type Page struct { + Source GeneratedType `json:"source,omitempty"` + Build_type string `json:"build_type,omitempty"` // The process in which the Page will be built. + Custom_404 bool `json:"custom_404"` // Whether the Page has a custom 404 page. + Html_url string `json:"html_url,omitempty"` // The web address the Page can be accessed from. + Cname string `json:"cname"` // The Pages site's custom domain + Https_certificate GeneratedType `json:"https_certificate,omitempty"` + Https_enforced bool `json:"https_enforced,omitempty"` // Whether https is enabled on the domain + Protected_domain_state string `json:"protected_domain_state,omitempty"` // The state if the domain is verified + Url string `json:"url"` // The API address for accessing this Page resource. + Pending_domain_unverified_at string `json:"pending_domain_unverified_at,omitempty"` // The timestamp when a pending domain becomes unverified. + Public bool `json:"public"` // Whether the GitHub Pages site is publicly visible. If set to `true`, the site is accessible to anyone on the internet. If set to `false`, the site will only be accessible to users who have at least `read` access to the repository that published the site. + Status string `json:"status"` // The status of the most recent build of the Page. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action,omitempty"` + Check_run GeneratedType `json:"check_run"` // A check performed on the code of a given code change + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// Actor represents the Actor schema from the OpenAPI specification +type Actor struct { + Display_login string `json:"display_login,omitempty"` + Gravatar_id string `json:"gravatar_id"` + Id int `json:"id"` + Login string `json:"login"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Number int `json:"number"` + State string `json:"state"` + Created_at string `json:"created_at"` + Columns_url string `json:"columns_url"` + Updated_at string `json:"updated_at"` + Private bool `json:"private,omitempty"` // Whether the project is private or not. Only present when owner is an organization. + Owner_url string `json:"owner_url"` + Name string `json:"name"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Permissions map[string]interface{} `json:"permissions"` + Body string `json:"body"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Id int `json:"id"` + Organization_permission string `json:"organization_permission,omitempty"` // The organization permission for this project. Only present when owner is an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Url string `json:"url"` + Event string `json:"event"` + Id int `json:"id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Commit_id string `json:"commit_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Push_protection_bypass_request_reviewer GeneratedType `json:"push_protection_bypass_request_reviewer,omitempty"` // A GitHub user. + Url string `json:"url,omitempty"` // The REST API URL of the alert resource. + Created_at string `json:"created_at,omitempty"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Html_url string `json:"html_url,omitempty"` // The GitHub URL of the alert resource. + Locations_url string `json:"locations_url,omitempty"` // The REST API URL of the code locations for this alert. + Publicly_leaked bool `json:"publicly_leaked,omitempty"` // Whether the detected secret was publicly leaked. + Resolved_at string `json:"resolved_at,omitempty"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Resolved_by GeneratedType `json:"resolved_by,omitempty"` // A GitHub user. + Push_protection_bypass_request_comment string `json:"push_protection_bypass_request_comment,omitempty"` // An optional comment when requesting a push protection bypass. + Resolution_comment string `json:"resolution_comment,omitempty"` // An optional comment to resolve an alert. + Push_protection_bypassed bool `json:"push_protection_bypassed,omitempty"` // Whether push protection was bypassed for the detected secret. + Push_protection_bypassed_by GeneratedType `json:"push_protection_bypassed_by,omitempty"` // A GitHub user. + Secret_type_display_name string `json:"secret_type_display_name,omitempty"` // User-friendly name for the detected secret, matching the `secret_type`. For a list of built-in patterns, see "[Supported secret scanning patterns](https://docs.github.com/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets)." + Number int `json:"number,omitempty"` // The security alert number. + Validity string `json:"validity,omitempty"` // The token status as of the latest validity check. + Push_protection_bypassed_at string `json:"push_protection_bypassed_at,omitempty"` // The time that push protection was bypassed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Push_protection_bypass_request_reviewer_comment string `json:"push_protection_bypass_request_reviewer_comment,omitempty"` // An optional comment when reviewing a push protection bypass. + Resolution string `json:"resolution,omitempty"` // The reason for resolving the alert. + Secret_type string `json:"secret_type,omitempty"` // The type of secret that secret scanning detected. + Multi_repo bool `json:"multi_repo,omitempty"` // Whether the detected secret was found in multiple repositories in the same organization or business. + Push_protection_bypass_request_html_url string `json:"push_protection_bypass_request_html_url,omitempty"` // The URL to a push protection bypass request. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Slug string `json:"slug"` // The slug url identifier for the enterprise. + Description string `json:"description,omitempty"` // A short description of the enterprise. + Created_at string `json:"created_at"` + Id int `json:"id"` // Unique identifier of the enterprise + Name string `json:"name"` // The name of the enterprise. + Updated_at string `json:"updated_at"` + Website_url string `json:"website_url,omitempty"` // The enterprise's website URL. + Avatar_url string `json:"avatar_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // Minimal Repository + Updated_at string `json:"updated_at,omitempty"` + Url string `json:"url,omitempty"` + Conclusion string `json:"conclusion,omitempty"` + Id int `json:"id,omitempty"` + After string `json:"after,omitempty"` + Before string `json:"before,omitempty"` + Head_sha string `json:"head_sha,omitempty"` // The SHA of the head commit that is being checked. + Status string `json:"status,omitempty"` + App Integration `json:"app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Created_at string `json:"created_at,omitempty"` + Head_branch string `json:"head_branch,omitempty"` + Node_id string `json:"node_id,omitempty"` + Pull_requests []GeneratedType `json:"pull_requests,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField GeneratedType `json:"type"` // The type of issue. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Value string `json:"value"` // The value assigned to the property + Property_name string `json:"property_name"` // The name of the property +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Repositories_removed []map[string]interface{} `json:"repositories_removed"` // An array of repository objects, which were removed from the installation. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Installation Installation `json:"installation"` // Installation + Requester Webhooksuser `json:"requester"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories_added []map[string]interface{} `json:"repositories_added"` // An array of repository objects, which were added to the installation. + Repository_selection string `json:"repository_selection"` // Describe whether all repositories have been selected or there's a selection involved +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` // Unique identifier of the classroom. + Name string `json:"name"` // The name of the classroom. + Url string `json:"url"` // The url of the classroom on GitHub Classroom. + Archived bool `json:"archived"` // Returns whether classroom is archived or not. +} + +// Webhooksrelease represents the Webhooksrelease schema from the OpenAPI specification +type Webhooksrelease struct { + Tag_name string `json:"tag_name"` // The name of the tag. + Tarball_url string `json:"tarball_url"` + Upload_url string `json:"upload_url"` + Author map[string]interface{} `json:"author"` + Draft bool `json:"draft"` // Whether the release is a draft or published + Url string `json:"url"` + Name string `json:"name"` + Prerelease bool `json:"prerelease"` // Whether the release is identified as a prerelease or a full release. + Published_at string `json:"published_at"` + Html_url string `json:"html_url"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + Discussion_url string `json:"discussion_url,omitempty"` + Id int `json:"id"` + Body string `json:"body"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Target_commitish string `json:"target_commitish"` // Specifies the commitish value that determines where the Git tag is created from. + Zipball_url string `json:"zipball_url"` + Assets []map[string]interface{} `json:"assets"` + Assets_url string `json:"assets_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Role_name string `json:"role_name,omitempty"` + Archive_url string `json:"archive_url"` + Pulls_url string `json:"pulls_url"` + Size int `json:"size,omitempty"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Downloads_url string `json:"downloads_url"` + Trees_url string `json:"trees_url"` + Has_discussions bool `json:"has_discussions,omitempty"` + Watchers int `json:"watchers,omitempty"` + Clone_url string `json:"clone_url,omitempty"` + Merges_url string `json:"merges_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Node_id string `json:"node_id"` + Collaborators_url string `json:"collaborators_url"` + Forks_count int `json:"forks_count,omitempty"` + Default_branch string `json:"default_branch,omitempty"` + Blobs_url string `json:"blobs_url"` + Name string `json:"name"` + Pushed_at string `json:"pushed_at,omitempty"` + Issue_comment_url string `json:"issue_comment_url"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Code_of_conduct GeneratedType `json:"code_of_conduct,omitempty"` // Code Of Conduct + Notifications_url string `json:"notifications_url"` + Ssh_url string `json:"ssh_url,omitempty"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Html_url string `json:"html_url"` + Forks_url string `json:"forks_url"` + Milestones_url string `json:"milestones_url"` + Events_url string `json:"events_url"` + Issue_events_url string `json:"issue_events_url"` + Forks int `json:"forks,omitempty"` + Url string `json:"url"` + Open_issues_count int `json:"open_issues_count,omitempty"` + Network_count int `json:"network_count,omitempty"` + Private bool `json:"private"` + Issues_url string `json:"issues_url"` + Language string `json:"language,omitempty"` + Labels_url string `json:"labels_url"` + Statuses_url string `json:"statuses_url"` + Id int64 `json:"id"` + Disabled bool `json:"disabled,omitempty"` + Contents_url string `json:"contents_url"` + Topics []string `json:"topics,omitempty"` + Branches_url string `json:"branches_url"` + Git_refs_url string `json:"git_refs_url"` + Visibility string `json:"visibility,omitempty"` + Contributors_url string `json:"contributors_url"` + Open_issues int `json:"open_issues,omitempty"` + Archived bool `json:"archived,omitempty"` + License map[string]interface{} `json:"license,omitempty"` + Stargazers_url string `json:"stargazers_url"` + Security_and_analysis GeneratedType `json:"security_and_analysis,omitempty"` + Description string `json:"description"` + Has_downloads bool `json:"has_downloads,omitempty"` + Commits_url string `json:"commits_url"` + Subscribers_url string `json:"subscribers_url"` + Watchers_count int `json:"watchers_count,omitempty"` + Hooks_url string `json:"hooks_url"` + Has_issues bool `json:"has_issues,omitempty"` + Git_commits_url string `json:"git_commits_url"` + Has_pages bool `json:"has_pages,omitempty"` + Compare_url string `json:"compare_url"` + Teams_url string `json:"teams_url"` + Svn_url string `json:"svn_url,omitempty"` + Allow_forking bool `json:"allow_forking,omitempty"` + Created_at string `json:"created_at,omitempty"` + Custom_properties map[string]interface{} `json:"custom_properties,omitempty"` // The custom properties that were defined for the repository. The keys are the custom property names, and the values are the corresponding custom property values. + Is_template bool `json:"is_template,omitempty"` + Releases_url string `json:"releases_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Homepage string `json:"homepage,omitempty"` + Assignees_url string `json:"assignees_url"` + Deployments_url string `json:"deployments_url"` + Languages_url string `json:"languages_url"` + Git_url string `json:"git_url,omitempty"` + Full_name string `json:"full_name"` + Stargazers_count int `json:"stargazers_count,omitempty"` + Comments_url string `json:"comments_url"` + Git_tags_url string `json:"git_tags_url"` + Fork bool `json:"fork"` + Updated_at string `json:"updated_at,omitempty"` + Subscription_url string `json:"subscription_url"` + Has_wiki bool `json:"has_wiki,omitempty"` + Has_projects bool `json:"has_projects,omitempty"` + Tags_url string `json:"tags_url"` + Mirror_url string `json:"mirror_url,omitempty"` + Keys_url string `json:"keys_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Email string `json:"email,omitempty"` + Id int `json:"id"` + Login string `json:"login"` + Node_id string `json:"node_id,omitempty"` + Organization_billing_email string `json:"organization_billing_email,omitempty"` + TypeField string `json:"type"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_card map[string]interface{} `json:"project_card"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Size int `json:"size"` // The size of the CodeQL database file in bytes. + Updated_at string `json:"updated_at"` // The date and time at which the CodeQL database was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Commit_oid string `json:"commit_oid,omitempty"` // The commit SHA of the repository at the time the CodeQL database was created. + Created_at string `json:"created_at"` // The date and time at which the CodeQL database was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Id int `json:"id"` // The ID of the CodeQL database. + Name string `json:"name"` // The name of the CodeQL database. + Language string `json:"language"` // The language of the CodeQL database. + Uploader GeneratedType `json:"uploader"` // A GitHub user. + Content_type string `json:"content_type"` // The MIME type of the CodeQL database file. + Url string `json:"url"` // The URL at which to download the CodeQL database. The `Accept` header must be set to the value of the `content_type` property. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Key string `json:"key"` // The Base64 encoded public key. + Key_id string `json:"key_id"` // The identifier for the key. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Comment map[string]interface{} `json:"comment"` // The [comment](https://docs.github.com/rest/pulls/comments#get-a-review-comment-for-a-pull-request) itself. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sub_issue Issue `json:"sub_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Parent_issue_id float64 `json:"parent_issue_id"` // The ID of the parent issue. + Sub_issue_id float64 `json:"sub_issue_id"` // The ID of the sub-issue. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Parent_issue Issue `json:"parent_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sub_issue_repo Repository `json:"sub_issue_repo"` // A repository on GitHub. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + First_patched_version map[string]interface{} `json:"first_patched_version"` // Details pertaining to the package version that patches this vulnerability. + PackageField GeneratedType `json:"package"` // Details for the vulnerable package. + Severity string `json:"severity"` // The severity of the vulnerability. + Vulnerable_version_range string `json:"vulnerable_version_range"` // Conditions that identify vulnerable versions of this vulnerability's package. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Page_url string `json:"page_url"` // The GitHub URL to get the associated wiki page + End_line float64 `json:"end_line"` // Line number at which the secret ends in the file + Start_column float64 `json:"start_column"` // The column at which the secret starts within the start line when the file is interpreted as 8-bit ASCII. + Start_line float64 `json:"start_line"` // Line number at which the secret starts in the file + Commit_sha string `json:"commit_sha"` // SHA-1 hash ID of the associated commit + Commit_url string `json:"commit_url"` // The GitHub URL to get the associated wiki commit + Path string `json:"path"` // The file path of the wiki page + Blob_sha string `json:"blob_sha"` // SHA-1 hash ID of the associated blob + End_column float64 `json:"end_column"` // The column at which the secret ends within the end line when the file is interpreted as 8-bit ASCII. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Payload string `json:"payload"` // A URL-encoded string of the check_run.completed JSON payload. The decoded payload is a JSON object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Registry_package map[string]interface{} `json:"registry_package"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Bypass_mode string `json:"bypass_mode,omitempty"` // When the specified actor can bypass the ruleset. `pull_request` means that an actor can only bypass rules on pull requests. `pull_request` is not applicable for the `DeployKey` actor type. Also, `pull_request` is only applicable to branch rulesets. + Actor_id int `json:"actor_id,omitempty"` // The ID of the actor that can bypass a ruleset. If `actor_type` is `OrganizationAdmin`, this should be `1`. If `actor_type` is `DeployKey`, this should be null. `OrganizationAdmin` is not applicable for personal repositories. + Actor_type string `json:"actor_type"` // The type of actor that can bypass a ruleset. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Thread map[string]interface{} `json:"thread"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// Collaborator represents the Collaborator schema from the OpenAPI specification +type Collaborator struct { + Site_admin bool `json:"site_admin"` + Events_url string `json:"events_url"` + Login string `json:"login"` + User_view_type string `json:"user_view_type,omitempty"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Avatar_url string `json:"avatar_url"` + Received_events_url string `json:"received_events_url"` + TypeField string `json:"type"` + Role_name string `json:"role_name"` + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` + Organizations_url string `json:"organizations_url"` + Subscriptions_url string `json:"subscriptions_url"` + Following_url string `json:"following_url"` + Node_id string `json:"node_id"` + Gravatar_id string `json:"gravatar_id"` + Url string `json:"url"` + Id int64 `json:"id"` + Starred_url string `json:"starred_url"` + Gists_url string `json:"gists_url"` + Followers_url string `json:"followers_url"` + Repos_url string `json:"repos_url"` + Html_url string `json:"html_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_reason string `json:"dismissed_reason"` // **Required when the state is dismissed.** The reason for dismissing or closing the alert. + Most_recent_instance GeneratedType `json:"most_recent_instance"` + Tool GeneratedType `json:"tool"` + Repository GeneratedType `json:"repository"` // A GitHub repository. + Fixed_at string `json:"fixed_at,omitempty"` // The time that the alert was no longer detected and was considered fixed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Number int `json:"number"` // The security alert number. + State string `json:"state"` // State of a code scanning alert. + Dismissal_approved_by GeneratedType `json:"dismissal_approved_by,omitempty"` // A GitHub user. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Instances_url string `json:"instances_url"` // The REST API URL for fetching the list of instances for an alert. + Rule GeneratedType `json:"rule"` + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Url string `json:"url"` // The REST API URL of the alert resource. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_comment string `json:"dismissed_comment,omitempty"` // The dismissal comment associated with the dismissal of the alert. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert map[string]interface{} `json:"alert"` // The security alert of the vulnerable dependency. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Source string `json:"source"` // The image provider. + Display_name string `json:"display_name"` // Display name for this image. + Id string `json:"id"` // The ID of the image. Use this ID for the `image` parameter when creating a new larger runner. + Size_gb int `json:"size_gb"` // Image size in GB. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Details interface{} `json:"details,omitempty"` + TypeField string `json:"type,omitempty"` // The location type. Because secrets may be found in different types of resources (ie. code, comments, issues, pull requests, discussions), this field identifies the type of resource where the secret was found. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Number int `json:"number"` + Reason string `json:"reason"` + Action string `json:"action"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Pull_request map[string]interface{} `json:"pull_request"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow_job map[string]interface{} `json:"workflow_job"` + Action string `json:"action"` + Deployment Deployment `json:"deployment,omitempty"` // A request for a specific ref(branch,sha,tag) to be deployed + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue2 `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Size int `json:"size"` + TypeField string `json:"type"` + Encoding string `json:"encoding,omitempty"` + Git_url string `json:"git_url"` + Html_url string `json:"html_url"` + Links map[string]interface{} `json:"_links"` + Content string `json:"content,omitempty"` + Download_url string `json:"download_url"` + Path string `json:"path"` + Sha string `json:"sha"` + Url string `json:"url"` + Entries []map[string]interface{} `json:"entries,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Project_card map[string]interface{} `json:"project_card,omitempty"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` + Node_id string `json:"node_id"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Commit_id string `json:"commit_id"` + Event string `json:"event"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Expires_at string `json:"expires_at"` + Limit string `json:"limit"` // The type of GitHub user that can comment, open issues, or create pull requests while the interaction limit is in effect. + Origin string `json:"origin"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the secret + Selected_repositories_url string `json:"selected_repositories_url"` // The API URL at which the list of repositories this secret is visible to can be retrieved + Updated_at string `json:"updated_at"` // The date and time at which the secret was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Visibility string `json:"visibility"` // The type of repositories in the organization that the secret is visible to + Created_at string `json:"created_at"` // The date and time at which the secret was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Assignee Webhooksusermannequin `json:"assignee,omitempty"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Number int `json:"number"` // The pull request number. + Pull_request map[string]interface{} `json:"pull_request"` + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes Webhooksprojectchanges `json:"changes"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Changes Webhookschanges `json:"changes"` // The changes to the comment. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender"` // A GitHub user. + Comment Webhooksreviewcomment `json:"comment"` // The [comment](https://docs.github.com/rest/pulls/comments#get-a-review-comment-for-a-pull-request) itself. + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Reviewers []map[string]interface{} `json:"reviewers,omitempty"` + Since string `json:"since"` + Approver Webhooksapprover `json:"approver,omitempty"` + Workflow_job_runs []map[string]interface{} `json:"workflow_job_runs,omitempty"` + Workflow_run map[string]interface{} `json:"workflow_run"` + Action string `json:"action"` + Comment string `json:"comment,omitempty"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow_job_run Webhooksworkflowjobrun `json:"workflow_job_run,omitempty"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// License represents the License schema from the OpenAPI specification +type License struct { + Html_url string `json:"html_url"` + Implementation string `json:"implementation"` + Key string `json:"key"` + Name string `json:"name"` + Spdx_id string `json:"spdx_id"` + Body string `json:"body"` + Conditions []string `json:"conditions"` + Limitations []string `json:"limitations"` + Description string `json:"description"` + Featured bool `json:"featured"` + Url string `json:"url"` + Node_id string `json:"node_id"` + Permissions []string `json:"permissions"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Members_can_create_private_pages bool `json:"members_can_create_private_pages,omitempty"` + Members_can_create_repositories bool `json:"members_can_create_repositories,omitempty"` + Secret_scanning_enabled_for_new_repositories bool `json:"secret_scanning_enabled_for_new_repositories,omitempty"` // **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead. Whether secret scanning is automatically enabled for new repositories and repositories transferred to this organization. This field is only visible to organization owners or members of a team with the security manager role. + Email string `json:"email,omitempty"` + Followers int `json:"followers"` + Two_factor_requirement_enabled bool `json:"two_factor_requirement_enabled,omitempty"` + Disk_usage int `json:"disk_usage,omitempty"` + Avatar_url string `json:"avatar_url"` + Description string `json:"description"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Has_repository_projects bool `json:"has_repository_projects"` + Deploy_keys_enabled_for_repositories bool `json:"deploy_keys_enabled_for_repositories,omitempty"` // Controls whether or not deploy keys may be added and used for repositories in the organization. + Members_can_create_public_pages bool `json:"members_can_create_public_pages,omitempty"` + Updated_at string `json:"updated_at"` + Id int `json:"id"` + Issues_url string `json:"issues_url"` + Members_can_view_dependency_insights bool `json:"members_can_view_dependency_insights,omitempty"` + Owned_private_repos int `json:"owned_private_repos,omitempty"` + Default_repository_branch string `json:"default_repository_branch,omitempty"` // The default branch for repositories created in this organization. + Has_organization_projects bool `json:"has_organization_projects"` + Location string `json:"location,omitempty"` + Html_url string `json:"html_url"` + Events_url string `json:"events_url"` + Public_members_url string `json:"public_members_url"` + Is_verified bool `json:"is_verified,omitempty"` + Members_can_invite_outside_collaborators bool `json:"members_can_invite_outside_collaborators,omitempty"` + Public_gists int `json:"public_gists"` + Url string `json:"url"` + Company string `json:"company,omitempty"` + Members_can_change_repo_visibility bool `json:"members_can_change_repo_visibility,omitempty"` + Login string `json:"login"` + Members_can_create_private_repositories bool `json:"members_can_create_private_repositories,omitempty"` + Name string `json:"name,omitempty"` + Collaborators int `json:"collaborators,omitempty"` // The number of collaborators on private repositories. This field may be null if the number of private repositories is over 50,000. + Members_can_create_teams bool `json:"members_can_create_teams,omitempty"` + Members_can_create_public_repositories bool `json:"members_can_create_public_repositories,omitempty"` + Billing_email string `json:"billing_email,omitempty"` + Members_can_fork_private_repositories bool `json:"members_can_fork_private_repositories,omitempty"` + Blog string `json:"blog,omitempty"` + Private_gists int `json:"private_gists,omitempty"` + Advanced_security_enabled_for_new_repositories bool `json:"advanced_security_enabled_for_new_repositories,omitempty"` // **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead. Whether GitHub Advanced Security is enabled for new repositories and repositories transferred to this organization. This field is only visible to organization owners or members of a team with the security manager role. + Members_can_delete_issues bool `json:"members_can_delete_issues,omitempty"` + Secret_scanning_push_protection_custom_link_enabled bool `json:"secret_scanning_push_protection_custom_link_enabled,omitempty"` // Whether a custom link is shown to contributors who are blocked from pushing a secret by push protection. + Following int `json:"following"` + Public_repos int `json:"public_repos"` + Total_private_repos int `json:"total_private_repos,omitempty"` + Repos_url string `json:"repos_url"` + Plan map[string]interface{} `json:"plan,omitempty"` + Created_at string `json:"created_at"` + Secret_scanning_push_protection_custom_link string `json:"secret_scanning_push_protection_custom_link,omitempty"` // An optional URL string to display to contributors who are blocked from pushing a secret. + Secret_scanning_push_protection_enabled_for_new_repositories bool `json:"secret_scanning_push_protection_enabled_for_new_repositories,omitempty"` // **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead. Whether secret scanning push protection is automatically enabled for new repositories and repositories transferred to this organization. This field is only visible to organization owners or members of a team with the security manager role. + Twitter_username string `json:"twitter_username,omitempty"` + Members_can_delete_repositories bool `json:"members_can_delete_repositories,omitempty"` + Members_can_create_internal_repositories bool `json:"members_can_create_internal_repositories,omitempty"` + Members_allowed_repository_creation_type string `json:"members_allowed_repository_creation_type,omitempty"` + Members_can_create_pages bool `json:"members_can_create_pages,omitempty"` + Node_id string `json:"node_id"` + Dependabot_alerts_enabled_for_new_repositories bool `json:"dependabot_alerts_enabled_for_new_repositories,omitempty"` // **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead. Whether Dependabot alerts are automatically enabled for new repositories and repositories transferred to this organization. This field is only visible to organization owners or members of a team with the security manager role. + Members_url string `json:"members_url"` + Default_repository_permission string `json:"default_repository_permission,omitempty"` + Display_commenter_full_name_setting_enabled bool `json:"display_commenter_full_name_setting_enabled,omitempty"` + Dependabot_security_updates_enabled_for_new_repositories bool `json:"dependabot_security_updates_enabled_for_new_repositories,omitempty"` // **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead. Whether Dependabot security updates are automatically enabled for new repositories and repositories transferred to this organization. This field is only visible to organization owners or members of a team with the security manager role. + Readers_can_create_discussions bool `json:"readers_can_create_discussions,omitempty"` + Dependency_graph_enabled_for_new_repositories bool `json:"dependency_graph_enabled_for_new_repositories,omitempty"` // **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead. Whether dependency graph is automatically enabled for new repositories and repositories transferred to this organization. This field is only visible to organization owners or members of a team with the security manager role. + Hooks_url string `json:"hooks_url"` + TypeField string `json:"type"` + Archived_at string `json:"archived_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Hooks_url string `json:"hooks_url"` + Repos_url string `json:"repos_url"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` + Description string `json:"description"` + Login string `json:"login"` + Members_url string `json:"members_url"` + Public_members_url string `json:"public_members_url"` + Issues_url string `json:"issues_url"` + Node_id string `json:"node_id"` + Events_url string `json:"events_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ecosystem string `json:"ecosystem"` // The package's language or package management ecosystem. + Name string `json:"name"` // The unique package name within its ecosystem. +} + +// Email represents the Email schema from the OpenAPI specification +type Email struct { + Email string `json:"email"` + Primary bool `json:"primary"` + Verified bool `json:"verified"` + Visibility string `json:"visibility"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // Full Repository + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// Artifact represents the Artifact schema from the OpenAPI specification +type Artifact struct { + Url string `json:"url"` + Expired bool `json:"expired"` // Whether or not the artifact has expired. + Updated_at string `json:"updated_at"` + Workflow_run map[string]interface{} `json:"workflow_run,omitempty"` + Archive_download_url string `json:"archive_download_url"` + Digest string `json:"digest,omitempty"` // The SHA256 digest of the artifact. This field will only be populated on artifacts uploaded with upload-artifact v4 or newer. For older versions, this field will be null. + Size_in_bytes int `json:"size_in_bytes"` // The size in bytes of the artifact. + Created_at string `json:"created_at"` + Expires_at string `json:"expires_at"` + Id int `json:"id"` + Name string `json:"name"` // The name of the artifact. + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Usageitems []map[string]interface{} `json:"usageItems,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Repository_ruleset GeneratedType `json:"repository_ruleset"` // A set of rules to apply when specified conditions are met. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// Webhooksissue2 represents the Webhooksissue2 schema from the OpenAPI specification +type Webhooksissue2 struct { + Active_lock_reason string `json:"active_lock_reason"` + Performed_via_github_app map[string]interface{} `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Assignee map[string]interface{} `json:"assignee,omitempty"` + Assignees []map[string]interface{} `json:"assignees"` + Draft bool `json:"draft,omitempty"` + Timeline_url string `json:"timeline_url,omitempty"` + Created_at string `json:"created_at"` + Repository_url string `json:"repository_url"` + Events_url string `json:"events_url"` + Closed_at string `json:"closed_at"` + Comments_url string `json:"comments_url"` + State string `json:"state,omitempty"` // State of the issue; either 'open' or 'closed' + Url string `json:"url"` // URL for the issue + Html_url string `json:"html_url"` + Comments int `json:"comments"` + Sub_issues_summary map[string]interface{} `json:"sub_issues_summary,omitempty"` + Body string `json:"body"` // Contents of the issue + User map[string]interface{} `json:"user"` + Reactions map[string]interface{} `json:"reactions"` + State_reason string `json:"state_reason,omitempty"` + Updated_at string `json:"updated_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Id int64 `json:"id"` + Locked bool `json:"locked,omitempty"` + Number int `json:"number"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Labels_url string `json:"labels_url"` + Labels []map[string]interface{} `json:"labels,omitempty"` + Milestone map[string]interface{} `json:"milestone"` // A collection of related issues and pull requests. + Node_id string `json:"node_id"` + Title string `json:"title"` // Title of the issue + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2 GeneratedType `json:"projects_v2"` // A projects v2 project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Milestone Webhooksmilestone `json:"milestone"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sbom map[string]interface{} `json:"sbom"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor GeneratedType `json:"actor"` // A GitHub user. + State_reason string `json:"state_reason,omitempty"` + Commit_id string `json:"commit_id"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Source string `json:"source,omitempty"` // Source answers the question, "where did this role come from?" + Updated_at string `json:"updated_at"` // The date and time the role was last updated. + Base_role string `json:"base_role,omitempty"` // The system role from which this role inherits permissions. + Created_at string `json:"created_at"` // The date and time the role was created. + Description string `json:"description,omitempty"` // A short description about who this role is for or what permissions it grants. + Id int64 `json:"id"` // The unique identifier of the role. + Name string `json:"name"` // The name of the role. + Organization GeneratedType `json:"organization"` // A GitHub user. + Permissions []string `json:"permissions"` // A list of permissions included in this role. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Protected bool `json:"protected"` + Commit map[string]interface{} `json:"commit"` + Name string `json:"name"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id string `json:"id"` // The ID of the image. Use this ID for the `image` parameter when creating a new larger runner. + Platform string `json:"platform"` // The operating system of the image. + Size_gb int `json:"size_gb"` // Image size in GB. + Source string `json:"source"` // The image provider. + Display_name string `json:"display_name"` // Display name for this image. +} + +// Environment represents the Environment schema from the OpenAPI specification +type Environment struct { + Node_id string `json:"node_id"` + Protection_rules []interface{} `json:"protection_rules,omitempty"` // Built-in deployment protection rules for the environment. + Url string `json:"url"` + Deployment_branch_policy GeneratedType `json:"deployment_branch_policy,omitempty"` // The type of deployment branch policy for this environment. To allow all branches to deploy, set to `null`. + Html_url string `json:"html_url"` + Updated_at string `json:"updated_at"` // The time that the environment was last updated, in ISO 8601 format. + Created_at string `json:"created_at"` // The time that the environment was created, in ISO 8601 format. + Id int64 `json:"id"` // The id of the environment. + Name string `json:"name"` // The name of the environment. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Documentation_url string `json:"documentation_url"` + Errors []string `json:"errors,omitempty"` + Message string `json:"message"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Message string `json:"message,omitempty"` + Base_branch string `json:"base_branch,omitempty"` + Merge_type string `json:"merge_type,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sha string `json:"sha"` // The Commit SHA. + Avatar_url string `json:"avatar_url,omitempty"` + Name string `json:"name"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Branches []map[string]interface{} `json:"branches"` // An array of branch objects containing the status' SHA. Each branch contains the given SHA, but the SHA may or may not be the head of the branch. The array includes a maximum of 10 branches. + Id int `json:"id"` // The unique identifier of the status. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Description string `json:"description"` // The optional human-readable description added to the status. + Sender GeneratedType `json:"sender"` // A GitHub user. + Target_url string `json:"target_url"` // The optional link added to the status. + Commit map[string]interface{} `json:"commit"` + Context string `json:"context"` + Created_at string `json:"created_at"` + State string `json:"state"` // The new state. Can be `pending`, `success`, `failure`, or `error`. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Cvss_v3 map[string]interface{} `json:"cvss_v3,omitempty"` + Cvss_v4 map[string]interface{} `json:"cvss_v4,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Push_protection_bypass_request_reviewer_comment string `json:"push_protection_bypass_request_reviewer_comment,omitempty"` // An optional comment when reviewing a push protection bypass. + Is_base64_encoded bool `json:"is_base64_encoded,omitempty"` // A boolean value representing whether or not alert is base64 encoded + Resolution string `json:"resolution,omitempty"` // **Required when the `state` is `resolved`.** The reason for resolving the alert. + Resolution_comment string `json:"resolution_comment,omitempty"` // The comment that was optionally added when this alert was closed + Created_at string `json:"created_at,omitempty"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + State string `json:"state,omitempty"` // Sets the state of the secret scanning alert. You must provide `resolution` when you set the state to `resolved`. + Validity string `json:"validity,omitempty"` // The token status as of the latest validity check. + Number int `json:"number,omitempty"` // The security alert number. + Publicly_leaked bool `json:"publicly_leaked,omitempty"` // Whether the secret was publicly leaked. + Push_protection_bypass_request_comment string `json:"push_protection_bypass_request_comment,omitempty"` // An optional comment when requesting a push protection bypass. + Push_protection_bypassed_by GeneratedType `json:"push_protection_bypassed_by,omitempty"` // A GitHub user. + Secret string `json:"secret,omitempty"` // The secret that was detected. + Secret_type_display_name string `json:"secret_type_display_name,omitempty"` // User-friendly name for the detected secret, matching the `secret_type`. For a list of built-in patterns, see "[Supported secret scanning patterns](https://docs.github.com/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets)." + Push_protection_bypassed bool `json:"push_protection_bypassed,omitempty"` // Whether push protection was bypassed for the detected secret. + Resolved_at string `json:"resolved_at,omitempty"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Url string `json:"url,omitempty"` // The REST API URL of the alert resource. + Secret_type string `json:"secret_type,omitempty"` // The type of secret that secret scanning detected. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Has_more_locations bool `json:"has_more_locations,omitempty"` // A boolean value representing whether or not the token in the alert was detected in more than one location. + Push_protection_bypass_request_reviewer GeneratedType `json:"push_protection_bypass_request_reviewer,omitempty"` // A GitHub user. + Push_protection_bypassed_at string `json:"push_protection_bypassed_at,omitempty"` // The time that push protection was bypassed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Resolved_by GeneratedType `json:"resolved_by,omitempty"` // A GitHub user. + Locations_url string `json:"locations_url,omitempty"` // The REST API URL of the code locations for this alert. + First_location_detected GeneratedType `json:"first_location_detected,omitempty"` // Details on the location where the token was initially detected. This can be a commit, wiki commit, issue, discussion, pull request. + Push_protection_bypass_request_html_url string `json:"push_protection_bypass_request_html_url,omitempty"` // The URL to a push protection bypass request. + Repository GeneratedType `json:"repository,omitempty"` // A GitHub repository. + Multi_repo bool `json:"multi_repo,omitempty"` // Whether the detected secret was found in multiple repositories in the same organization or enterprise. + Html_url string `json:"html_url,omitempty"` // The GitHub URL of the alert resource. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Milestone Webhooksmilestone3 `json:"milestone"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` // The global node ID of the installation. + Id int `json:"id"` // The ID of the installation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at,omitempty"` + Id int `json:"id"` + Key string `json:"key"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Payload string `json:"payload"` // A URL-encoded string of the check_run.rerequested JSON payload. The decoded payload is a JSON object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` // The action performed. Can be `created`. + Comment map[string]interface{} `json:"comment"` // The [commit comment](${externalDocsUpapp/api/description/components/schemas/webhooks/issue-comment-created.yamlrl}/rest/commits/comments#get-a-commit-comment) resource. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// Tag represents the Tag schema from the OpenAPI specification +type Tag struct { + Name string `json:"name"` + Node_id string `json:"node_id"` + Tarball_url string `json:"tarball_url"` + Zipball_url string `json:"zipball_url"` + Commit map[string]interface{} `json:"commit"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request_body_url string `json:"pull_request_body_url"` // The API URL to get the pull request where the secret was detected. +} + +// Language represents the Language schema from the OpenAPI specification +type Language struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Failed_at string `json:"failed_at,omitempty"` + Id int64 `json:"id"` + Inviter GeneratedType `json:"inviter"` // A GitHub user. + Email string `json:"email"` + Invitation_source string `json:"invitation_source,omitempty"` + Invitation_teams_url string `json:"invitation_teams_url"` + Role string `json:"role"` + Created_at string `json:"created_at"` + Login string `json:"login"` + Failed_reason string `json:"failed_reason,omitempty"` + Node_id string `json:"node_id"` + Team_count int `json:"team_count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repos_url string `json:"repos_url"` + Created_at string `json:"created_at"` + Html_url string `json:"html_url"` + Owned_private_repos int `json:"owned_private_repos"` + Hireable bool `json:"hireable"` + Url string `json:"url"` + Following int `json:"following"` + Two_factor_authentication bool `json:"two_factor_authentication"` + Organizations_url string `json:"organizations_url"` + Bio string `json:"bio"` + Starred_url string `json:"starred_url"` + Collaborators int `json:"collaborators"` + Name string `json:"name"` + Updated_at string `json:"updated_at"` + Login string `json:"login"` + Avatar_url string `json:"avatar_url"` + Site_admin bool `json:"site_admin"` + Received_events_url string `json:"received_events_url"` + User_view_type string `json:"user_view_type,omitempty"` + Events_url string `json:"events_url"` + Followers_url string `json:"followers_url"` + Business_plus bool `json:"business_plus,omitempty"` + Public_repos int `json:"public_repos"` + Company string `json:"company"` + Subscriptions_url string `json:"subscriptions_url"` + Location string `json:"location"` + Email string `json:"email"` + Disk_usage int `json:"disk_usage"` + Gravatar_id string `json:"gravatar_id"` + TypeField string `json:"type"` + Public_gists int `json:"public_gists"` + Total_private_repos int `json:"total_private_repos"` + Blog string `json:"blog"` + Following_url string `json:"following_url"` + Id int64 `json:"id"` + Followers int `json:"followers"` + Notification_email string `json:"notification_email,omitempty"` + Gists_url string `json:"gists_url"` + Node_id string `json:"node_id"` + Plan map[string]interface{} `json:"plan,omitempty"` + Private_gists int `json:"private_gists"` + Twitter_username string `json:"twitter_username,omitempty"` + Ldap_dn string `json:"ldap_dn,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Committed_at string `json:"committed_at"` + Url string `json:"url"` + User GeneratedType `json:"user"` // A GitHub user. + Version string `json:"version"` + Change_status map[string]interface{} `json:"change_status"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the repository. + Git_commits_url string `json:"git_commits_url"` // A template for the API URL to get information about Git commits of the repository. + Archive_url string `json:"archive_url"` // A template for the API URL to download the repository as an archive. + Url string `json:"url"` // The URL to get more information about the repository from the GitHub API. + Milestones_url string `json:"milestones_url"` // A template for the API URL to get information about milestones of the repository. + Trees_url string `json:"trees_url"` // A template for the API URL to create or retrieve a raw Git tree of the repository. + Issues_url string `json:"issues_url"` // A template for the API URL to get information about issues on the repository. + Pulls_url string `json:"pulls_url"` // A template for the API URL to get information about pull requests on the repository. + Blobs_url string `json:"blobs_url"` // A template for the API URL to create or retrieve a raw Git blob in the repository. + Git_tags_url string `json:"git_tags_url"` // A template for the API URL to get information about Git tags of the repository. + Branches_url string `json:"branches_url"` // A template for the API URL to get information about branches in the repository. + Hooks_url string `json:"hooks_url"` // The API URL to list the hooks on the repository. + Id int64 `json:"id"` // A unique identifier of the repository. + Private bool `json:"private"` // Whether the repository is private. + Commits_url string `json:"commits_url"` // A template for the API URL to get information about commits on the repository. + Notifications_url string `json:"notifications_url"` // A template for the API URL to get information about notifications on the repository. + Issue_events_url string `json:"issue_events_url"` // A template for the API URL to get information about issue events on the repository. + Languages_url string `json:"languages_url"` // The API URL to get information about the languages of the repository. + Assignees_url string `json:"assignees_url"` // A template for the API URL to list the available assignees for issues in the repository. + Collaborators_url string `json:"collaborators_url"` // A template for the API URL to get information about collaborators of the repository. + Full_name string `json:"full_name"` // The full, globally unique, name of the repository. + Node_id string `json:"node_id"` // The GraphQL identifier of the repository. + Fork bool `json:"fork"` // Whether the repository is a fork. + Labels_url string `json:"labels_url"` // A template for the API URL to get information about labels of the repository. + Merges_url string `json:"merges_url"` // The API URL to merge branches in the repository. + Statuses_url string `json:"statuses_url"` // A template for the API URL to get information about statuses of a commit. + Stargazers_url string `json:"stargazers_url"` // The API URL to list the stargazers on the repository. + Description string `json:"description"` // The repository description. + Releases_url string `json:"releases_url"` // A template for the API URL to get information about releases on the repository. + Deployments_url string `json:"deployments_url"` // The API URL to list the deployments of the repository. + Comments_url string `json:"comments_url"` // A template for the API URL to get information about comments on the repository. + Keys_url string `json:"keys_url"` // A template for the API URL to get information about deploy keys on the repository. + Owner GeneratedType `json:"owner"` // A GitHub user. + Contents_url string `json:"contents_url"` // A template for the API URL to get the contents of the repository. + Contributors_url string `json:"contributors_url"` // A template for the API URL to list the contributors to the repository. + Subscribers_url string `json:"subscribers_url"` // The API URL to list the subscribers on the repository. + Issue_comment_url string `json:"issue_comment_url"` // A template for the API URL to get information about issue comments on the repository. + Forks_url string `json:"forks_url"` // The API URL to list the forks of the repository. + Downloads_url string `json:"downloads_url"` // The API URL to list the downloads on the repository. + Events_url string `json:"events_url"` // The API URL to list the events of the repository. + Tags_url string `json:"tags_url"` // The API URL to get information about tags on the repository. + Subscription_url string `json:"subscription_url"` // The API URL to subscribe to notifications for this repository. + Teams_url string `json:"teams_url"` // The API URL to list the teams on the repository. + Compare_url string `json:"compare_url"` // A template for the API URL to compare two commits or refs. + Git_refs_url string `json:"git_refs_url"` // A template for the API URL to get information about Git refs of the repository. + Html_url string `json:"html_url"` // The URL to view the repository on GitHub.com. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Ref string `json:"ref"` // The Git reference of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Commit_oid string `json:"commit_oid"` // The commit SHA of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Id int `json:"id"` // The unique identifier of the project column + Name string `json:"name"` // Name of the project column + Node_id string `json:"node_id"` + Project_url string `json:"project_url"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Cards_url string `json:"cards_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Avatar_url string `json:"avatar_url"` + Events_url string `json:"events_url"` + Hooks_url string `json:"hooks_url"` + Members_url string `json:"members_url"` + Node_id string `json:"node_id"` + Description string `json:"description"` + Public_members_url string `json:"public_members_url"` + Url string `json:"url"` + Id int `json:"id"` + Issues_url string `json:"issues_url"` + Login string `json:"login"` + Repos_url string `json:"repos_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Visibility string `json:"visibility"` // Which type of organization repositories have access to the private registry. + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the private registry configuration. + Registry_type string `json:"registry_type"` // The registry type. + Updated_at string `json:"updated_at"` + Username string `json:"username,omitempty"` // The username to use when authenticating with the private registry. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Answer Webhooksanswer `json:"answer"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Analyses_url string `json:"analyses_url,omitempty"` // The REST API URL for getting the analyses associated with the upload. + Errors []string `json:"errors,omitempty"` // Any errors that ocurred during processing of the delivery. + Processing_status string `json:"processing_status,omitempty"` // `pending` files have not yet been processed, while `complete` means results from the SARIF have been stored. `failed` files have either not been processed at all, or could only be partially processed. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes Webhookschanges8 `json:"changes"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Sponsorship Webhookssponsorship `json:"sponsorship"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Action string `json:"action"` + Effective_date string `json:"effective_date,omitempty"` // The `pending_cancellation` and `pending_tier_change` event types will include the date the cancellation or tier change will take effect. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Event string `json:"event"` + Reactions GeneratedType `json:"reactions,omitempty"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Actor GeneratedType `json:"actor"` // A GitHub user. + Html_url string `json:"html_url"` + Issue_url string `json:"issue_url"` + Updated_at string `json:"updated_at"` + Body_html string `json:"body_html,omitempty"` + Id int `json:"id"` // Unique identifier of the issue comment + Body string `json:"body,omitempty"` // Contents of the issue comment + User GeneratedType `json:"user"` // A GitHub user. + Body_text string `json:"body_text,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Url string `json:"url"` // URL for the issue comment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Environment_name string `json:"environment_name"` // The name of the environment to approve or reject. + Comment string `json:"comment"` // Comment associated with the pending deployment protection rule. **Required when state is not provided.** +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request_review_url string `json:"pull_request_review_url"` // The API URL to get the pull request review where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Message string `json:"message"` + Sha string `json:"sha"` + Merged bool `json:"merged"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description,omitempty"` + Homepage string `json:"homepage,omitempty"` + Name string `json:"name,omitempty"` + Version_info map[string]interface{} `json:"version_info,omitempty"` + Commit_oid string `json:"commit_oid,omitempty"` + Dependencies []map[string]interface{} `json:"dependencies,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Platform string `json:"platform,omitempty"` + Readme string `json:"readme,omitempty"` + Repo string `json:"repo,omitempty"` +} + +// Blob represents the Blob schema from the OpenAPI specification +type Blob struct { + Highlighted_content string `json:"highlighted_content,omitempty"` + Node_id string `json:"node_id"` + Sha string `json:"sha"` + Size int `json:"size"` + Url string `json:"url"` + Content string `json:"content"` + Encoding string `json:"encoding"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Project_id int `json:"project_id"` + Project_url string `json:"project_url"` + Url string `json:"url"` + Column_name string `json:"column_name"` + Id int `json:"id"` + Previous_column_name string `json:"previous_column_name,omitempty"` +} + +// Stargazer represents the Stargazer schema from the OpenAPI specification +type Stargazer struct { + Starred_at string `json:"starred_at"` + User GeneratedType `json:"user"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Aliases []map[string]interface{} `json:"aliases,omitempty"` + Logo_url string `json:"logo_url,omitempty"` + Score float64 `json:"score"` + Repository_count int `json:"repository_count,omitempty"` + Released string `json:"released"` + Name string `json:"name"` + Created_at string `json:"created_at"` + Featured bool `json:"featured"` + Description string `json:"description"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Display_name string `json:"display_name"` + Related []map[string]interface{} `json:"related,omitempty"` + Short_description string `json:"short_description"` + Created_by string `json:"created_by"` + Curated bool `json:"curated"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Full_description string `json:"full_description,omitempty"` // A description of the rule used to detect the alert. + Id string `json:"id,omitempty"` // A unique identifier for the rule used to detect the alert. + Name string `json:"name,omitempty"` // The name of the rule used to detect the alert. + Severity string `json:"severity,omitempty"` // The severity of the alert. + Tags []string `json:"tags,omitempty"` // A set of tags applicable for the rule. + Help string `json:"help,omitempty"` // Detailed documentation for the rule as GitHub Flavored Markdown. + Security_severity_level string `json:"security_severity_level,omitempty"` // The security severity of the alert. + Description string `json:"description,omitempty"` // A short description of the rule used to detect the alert. + Help_uri string `json:"help_uri,omitempty"` // A link to the documentation for the rule used to detect the alert. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Custom_branch_policies bool `json:"custom_branch_policies"` // Whether only branches that match the specified name patterns can deploy to this environment. If `custom_branch_policies` is `true`, `protected_branches` must be `false`; if `custom_branch_policies` is `false`, `protected_branches` must be `true`. + Protected_branches bool `json:"protected_branches"` // Whether only branches with branch protection rules can deploy to this environment. If `protected_branches` is `true`, `custom_branch_policies` must be `false`; if `protected_branches` is `false`, `custom_branch_policies` must be `true`. +} + +// Webhookschanges8 represents the Webhookschanges8 schema from the OpenAPI specification +type Webhookschanges8 struct { + Tier map[string]interface{} `json:"tier"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// Vulnerability represents the Vulnerability schema from the OpenAPI specification +type Vulnerability struct { + First_patched_version string `json:"first_patched_version"` // The package version that resolves the vulnerability. + PackageField map[string]interface{} `json:"package"` // The name of the package affected by the vulnerability. + Vulnerable_functions []string `json:"vulnerable_functions"` // The functions in the package that are affected by the vulnerability. + Vulnerable_version_range string `json:"vulnerable_version_range"` // The range of the package versions affected by the vulnerability. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action,omitempty"` + Alert GeneratedType `json:"alert"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Location GeneratedType `json:"location"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes Webhookschanges8 `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Sponsorship Webhookssponsorship `json:"sponsorship"` + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Importer []string `json:"importer,omitempty"` + Git []string `json:"git,omitempty"` + Hooks []string `json:"hooks,omitempty"` + Ssh_keys []string `json:"ssh_keys,omitempty"` + Actions_macos []string `json:"actions_macos,omitempty"` + Dependabot []string `json:"dependabot,omitempty"` + Ssh_key_fingerprints map[string]interface{} `json:"ssh_key_fingerprints,omitempty"` + Codespaces []string `json:"codespaces,omitempty"` + Copilot []string `json:"copilot,omitempty"` + Domains map[string]interface{} `json:"domains,omitempty"` + Pages []string `json:"pages,omitempty"` + Github_enterprise_importer []string `json:"github_enterprise_importer,omitempty"` + Packages []string `json:"packages,omitempty"` + Verifiable_password_authentication bool `json:"verifiable_password_authentication"` + Actions []string `json:"actions,omitempty"` + Api []string `json:"api,omitempty"` + Web []string `json:"web,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Commit_id string `json:"commit_id"` + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Rename map[string]interface{} `json:"rename"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Id int `json:"id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Version string `json:"version,omitempty"` // The version of the tool used to generate the code scanning analysis. + Guid string `json:"guid,omitempty"` // The GUID of the tool used to generate the code scanning analysis, if provided in the uploaded SARIF data. + Name string `json:"name,omitempty"` // The name of the tool used to generate the code scanning analysis. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alerts_threshold string `json:"alerts_threshold"` // The severity level at which code scanning results that raise alerts block a reference update. For more information on alert severity levels, see "[About code scanning alerts](https://docs.github.com/code-security/code-scanning/managing-code-scanning-alerts/about-code-scanning-alerts#about-alert-severity-and-security-severity-levels)." + Security_alerts_threshold string `json:"security_alerts_threshold"` // The severity level at which code scanning results that raise security alerts block a reference update. For more information on security severity levels, see "[About code scanning alerts](https://docs.github.com/code-security/code-scanning/managing-code-scanning-alerts/about-code-scanning-alerts#about-alert-severity-and-security-severity-levels)." + Tool string `json:"tool"` // The name of a code scanning tool +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation Installation `json:"installation"` // Installation + Repositories_removed []map[string]interface{} `json:"repositories_removed"` // An array of repository objects, which were removed from the installation. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Repository_selection string `json:"repository_selection"` // Describe whether all repositories have been selected or there's a selection involved + Sender GeneratedType `json:"sender"` // A GitHub user. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Requester Webhooksuser `json:"requester"` + Action string `json:"action"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories_added []map[string]interface{} `json:"repositories_added"` // An array of repository objects, which were added to the installation. +} + +// Webhooksworkflow represents the Webhooksworkflow schema from the OpenAPI specification +type Webhooksworkflow struct { + Path string `json:"path"` + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Name string `json:"name"` + State string `json:"state"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Badge_url string `json:"badge_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_card Webhooksprojectcard `json:"project_card"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_column Webhooksprojectcolumn `json:"project_column"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enabled bool `json:"enabled,omitempty"` + Id int `json:"id,omitempty"` + Pattern string `json:"pattern"` + Updated_at string `json:"updated_at,omitempty"` + Created_at string `json:"created_at,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion_body_url string `json:"discussion_body_url"` // The URL to the discussion where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Color string `json:"color,omitempty"` // Color for the issue type. + Description string `json:"description,omitempty"` // Description of the issue type. + Is_enabled bool `json:"is_enabled"` // Whether or not the issue type is enabled at the organization level. + Name string `json:"name"` // Name of the issue type. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Milestone Webhooksmilestone `json:"milestone,omitempty"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Release Webhooksrelease1 `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Created_at string `json:"created_at"` + Dismissed_review map[string]interface{} `json:"dismissed_review"` + Event string `json:"event"` + Commit_url string `json:"commit_url"` + Id int `json:"id"` + Commit_id string `json:"commit_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Client_payload map[string]interface{} `json:"client_payload"` // The `client_payload` that was specified in the `POST /repos/{owner}/{repo}/dispatches` request body. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` // The `event_type` that was specified in the `POST /repos/{owner}/{repo}/dispatches` request body. + Branch string `json:"branch"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Slug string `json:"slug"` + Node_id string `json:"node_id"` + Notification_setting string `json:"notification_setting,omitempty"` // The notification setting the team has set + Url string `json:"url"` // URL for the team + Id int `json:"id"` // Unique identifier of the team + Members_url string `json:"members_url"` + Name string `json:"name"` // Name of the team + Privacy string `json:"privacy,omitempty"` // The level of privacy this team should have + Description string `json:"description"` // Description of the team + Repositories_url string `json:"repositories_url"` + Html_url string `json:"html_url"` + Ldap_dn string `json:"ldap_dn,omitempty"` // Distinguished Name (DN) that team maps to within LDAP environment + Permission string `json:"permission"` // Permission that the team will have for its repositories +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alt_domain map[string]interface{} `json:"alt_domain,omitempty"` + Domain map[string]interface{} `json:"domain,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Issue_title_url string `json:"issue_title_url"` // The API URL to get the issue where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Sponsorship Webhookssponsorship `json:"sponsorship"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Commit_oid string `json:"commit_oid"` // The commit SHA of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Ref string `json:"ref"` // The Git reference of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Submitted int `json:"submitted"` // The number of students that have submitted the assignment. + Max_teams int `json:"max_teams,omitempty"` // The maximum allowable teams for the assignment. + Invitations_enabled bool `json:"invitations_enabled"` // Whether the invitation link is enabled. Visiting an enabled invitation link will accept the assignment. + Deadline string `json:"deadline"` // The time at which the assignment is due. + Public_repo bool `json:"public_repo"` // Whether an accepted assignment creates a public repository. + Invite_link string `json:"invite_link"` // The link that a student can use to accept the assignment. + Editor string `json:"editor"` // The selected editor for the assignment. + Language string `json:"language"` // The programming language used in the assignment. + Students_are_repo_admins bool `json:"students_are_repo_admins"` // Whether students are admins on created repository on accepted assignment. + Accepted int `json:"accepted"` // The number of students that have accepted the assignment. + Feedback_pull_requests_enabled bool `json:"feedback_pull_requests_enabled"` // Whether feedback pull request will be created on assignment acceptance. + Passing int `json:"passing"` // The number of students that have passed the assignment. + Classroom GeneratedType `json:"classroom"` // A GitHub Classroom classroom + Title string `json:"title"` // Assignment title. + TypeField string `json:"type"` // Whether it's a Group Assignment or Individual Assignment. + Slug string `json:"slug"` // Sluggified name of the assignment. + Id int `json:"id"` // Unique identifier of the repository. + Max_members int `json:"max_members,omitempty"` // The maximum allowable members per team. +} + +// Status represents the Status schema from the OpenAPI specification +type Status struct { + Created_at string `json:"created_at"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Id int `json:"id"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Context string `json:"context"` + Description string `json:"description"` + Target_url string `json:"target_url"` + Updated_at string `json:"updated_at"` + State string `json:"state"` + Avatar_url string `json:"avatar_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Can_approve_pull_request_reviews bool `json:"can_approve_pull_request_reviews,omitempty"` // Whether GitHub Actions can approve pull requests. Enabling this can be a security risk. + Default_workflow_permissions string `json:"default_workflow_permissions,omitempty"` // The default workflow permissions granted to the GITHUB_TOKEN when running workflows. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description"` // The campaign description + Ends_at string `json:"ends_at"` // The date and time the campaign has ended, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Name string `json:"name,omitempty"` // The campaign name + Number int `json:"number"` // The number of the newly created campaign + Team_managers []Team `json:"team_managers,omitempty"` // The campaign team managers + Created_at string `json:"created_at"` // The date and time the campaign was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Managers []GeneratedType `json:"managers"` // The campaign managers + Published_at string `json:"published_at,omitempty"` // The date and time the campaign was published, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Alert_stats map[string]interface{} `json:"alert_stats,omitempty"` + State string `json:"state"` // Indicates whether a campaign is open or closed + Updated_at string `json:"updated_at"` // The date and time the campaign was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Closed_at string `json:"closed_at,omitempty"` // The date and time the campaign was closed, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. Will be null if the campaign is still open. + Contact_link string `json:"contact_link"` // The contact link of the campaign. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Minutes_used_breakdown map[string]interface{} `json:"minutes_used_breakdown"` + Total_minutes_used int `json:"total_minutes_used"` // The sum of the free and paid GitHub Actions minutes used. + Total_paid_minutes_used int `json:"total_paid_minutes_used"` // The total paid GitHub Actions minutes used. + Included_minutes int `json:"included_minutes"` // The amount of free GitHub Actions minutes available. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Code_scanning_default_setup string `json:"code_scanning_default_setup,omitempty"` // The enablement status of code scanning default setup + Updated_at string `json:"updated_at,omitempty"` + Dependency_graph string `json:"dependency_graph,omitempty"` // The enablement status of Dependency Graph + Target_type string `json:"target_type,omitempty"` // The type of the code security configuration. + Advanced_security string `json:"advanced_security,omitempty"` // The enablement status of GitHub Advanced Security + Dependabot_alerts string `json:"dependabot_alerts,omitempty"` // The enablement status of Dependabot alerts + Dependabot_security_updates string `json:"dependabot_security_updates,omitempty"` // The enablement status of Dependabot security updates + Code_scanning_delegated_alert_dismissal string `json:"code_scanning_delegated_alert_dismissal,omitempty"` // The enablement status of code scanning delegated alert dismissal + Secret_scanning_generic_secrets string `json:"secret_scanning_generic_secrets,omitempty"` // The enablement status of Copilot secret scanning + Name string `json:"name,omitempty"` // The name of the code security configuration. Must be unique within the organization. + Secret_scanning_delegated_alert_dismissal string `json:"secret_scanning_delegated_alert_dismissal,omitempty"` // The enablement status of secret scanning delegated alert dismissal + Created_at string `json:"created_at,omitempty"` + Dependency_graph_autosubmit_action string `json:"dependency_graph_autosubmit_action,omitempty"` // The enablement status of Automatic dependency submission + Description string `json:"description,omitempty"` // A description of the code security configuration + Html_url string `json:"html_url,omitempty"` // The URL of the configuration + Id int `json:"id,omitempty"` // The ID of the code security configuration + Secret_scanning_non_provider_patterns string `json:"secret_scanning_non_provider_patterns,omitempty"` // The enablement status of secret scanning non-provider patterns + Code_scanning_options map[string]interface{} `json:"code_scanning_options,omitempty"` // Feature options for code scanning + Secret_scanning string `json:"secret_scanning,omitempty"` // The enablement status of secret scanning + Enforcement string `json:"enforcement,omitempty"` // The enforcement status for a security configuration + Secret_scanning_validity_checks string `json:"secret_scanning_validity_checks,omitempty"` // The enablement status of secret scanning validity checks + Secret_scanning_delegated_bypass string `json:"secret_scanning_delegated_bypass,omitempty"` // The enablement status of secret scanning delegated bypass + Code_scanning_default_setup_options map[string]interface{} `json:"code_scanning_default_setup_options,omitempty"` // Feature options for code scanning default setup + Secret_scanning_delegated_bypass_options map[string]interface{} `json:"secret_scanning_delegated_bypass_options,omitempty"` // Feature options for secret scanning delegated bypass + Dependency_graph_autosubmit_action_options map[string]interface{} `json:"dependency_graph_autosubmit_action_options,omitempty"` // Feature options for Automatic dependency submission + Url string `json:"url,omitempty"` // The URL of the configuration + Secret_scanning_push_protection string `json:"secret_scanning_push_protection,omitempty"` // The enablement status of secret scanning push protection + Private_vulnerability_reporting string `json:"private_vulnerability_reporting,omitempty"` // The enablement status of private vulnerability reporting +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Created_at string `json:"created_at"` + Ignored bool `json:"ignored"` + Reason string `json:"reason"` + Repository_url string `json:"repository_url,omitempty"` + Subscribed bool `json:"subscribed"` + Thread_url string `json:"thread_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Values_editable_by string `json:"values_editable_by,omitempty"` // Who can edit the values of the property + Allowed_values []string `json:"allowed_values,omitempty"` // An ordered list of the allowed values of the property. The property can have up to 200 allowed values. + Default_value string `json:"default_value,omitempty"` // Default value of the property + Description string `json:"description,omitempty"` // Short description of the property + Required bool `json:"required,omitempty"` // Whether the property is required. + Value_type string `json:"value_type"` // The type of the value for the property +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Summary string `json:"summary"` // A short, plain text summary of the advisory. + Identifiers []map[string]interface{} `json:"identifiers"` // Values that identify this advisory among security information sources. + Epss GeneratedType `json:"epss,omitempty"` // The EPSS scores as calculated by the [Exploit Prediction Scoring System](https://www.first.org/epss). + Cve_id string `json:"cve_id"` // The unique CVE ID assigned to the advisory. + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + Published_at string `json:"published_at"` // The time that the advisory was published in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Withdrawn_at string `json:"withdrawn_at"` // The time that the advisory was withdrawn in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Cvss map[string]interface{} `json:"cvss"` // Details for the advisory pertaining to the Common Vulnerability Scoring System. + Updated_at string `json:"updated_at"` // The time that the advisory was last modified in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Vulnerabilities []GeneratedType `json:"vulnerabilities"` // Vulnerable version range information for the advisory. + Cwes []map[string]interface{} `json:"cwes"` // Details for the advisory pertaining to Common Weakness Enumeration. + Ghsa_id string `json:"ghsa_id"` // The unique GitHub Security Advisory ID assigned to the advisory. + Severity string `json:"severity"` // The severity of the advisory. + Description string `json:"description"` // A long-form Markdown-supported description of the advisory. + References []map[string]interface{} `json:"references"` // Links to additional advisory information. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Check_suite map[string]interface{} `json:"check_suite"` // The [check_suite](https://docs.github.com/rest/checks/suites#get-a-check-suite). + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// Webhooksprojectchanges represents the Webhooksprojectchanges schema from the OpenAPI specification +type Webhooksprojectchanges struct { + Archived_at map[string]interface{} `json:"archived_at,omitempty"` +} + +// Webhooksproject represents the Webhooksproject schema from the OpenAPI specification +type Webhooksproject struct { + Owner_url string `json:"owner_url"` + Creator map[string]interface{} `json:"creator"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Created_at string `json:"created_at"` + Number int `json:"number"` + State string `json:"state"` // State of the project; either 'open' or 'closed' + Url string `json:"url"` + Columns_url string `json:"columns_url"` + Updated_at string `json:"updated_at"` + Body string `json:"body"` // Body of the project + Name string `json:"name"` // Name of the project + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Status string `json:"status,omitempty"` // The attachment status of the code security configuration on the repository. + Configuration GeneratedType `json:"configuration,omitempty"` // A code security configuration +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories []map[string]interface{} `json:"repositories,omitempty"` // An array of repository objects that the installation can access. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Requester interface{} `json:"requester,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation Installation `json:"installation"` // Installation +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Runner_type string `json:"runner_type,omitempty"` // Runner type to be used. + Schedule string `json:"schedule,omitempty"` // The frequency of the periodic analysis. + State string `json:"state,omitempty"` // Code scanning default setup has been configured or not. + Threat_model string `json:"threat_model,omitempty"` // Threat model to be used for code scanning analysis. Use `remote` to analyze only network sources and `remote_and_local` to include local sources like filesystem access, command-line arguments, database reads, environment variable and standard input. + Updated_at string `json:"updated_at,omitempty"` // Timestamp of latest configuration update. + Languages []string `json:"languages,omitempty"` // Languages to be analyzed. + Query_suite string `json:"query_suite,omitempty"` // CodeQL query suite to be used. + Runner_label string `json:"runner_label,omitempty"` // Runner label to be used if the runner type is labeled. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` // If the action was `edited`, the changes to the rule. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Rule Webhooksrule `json:"rule"` // The branch protection rule. Includes a `name` and all the [branch protection settings](https://docs.github.com/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#about-branch-protection-settings) applied to branches that match the name. Binary settings are boolean. Multi-level configurations are one of `off`, `non_admins`, or `everyone`. Actor and build lists are arrays of strings. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Allowed_values []string `json:"allowed_values,omitempty"` // An ordered list of the allowed values of the property. The property can have up to 200 allowed values. + Description string `json:"description,omitempty"` // Short description of the property + Property_name string `json:"property_name"` // The name of the property + Source_type string `json:"source_type,omitempty"` // The source type of the property + Url string `json:"url,omitempty"` // The URL that can be used to fetch, update, or delete info about this property via the API. + Required bool `json:"required,omitempty"` // Whether the property is required. + Value_type string `json:"value_type"` // The type of the value for the property + Values_editable_by string `json:"values_editable_by,omitempty"` // Who can edit the values of the property + Default_value string `json:"default_value,omitempty"` // Default value of the property +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request_review_comment_url string `json:"pull_request_review_comment_url"` // The API URL to get the pull request review comment where the secret was detected. +} + +// Deployment represents the Deployment schema from the OpenAPI specification +type Deployment struct { + Repository_url string `json:"repository_url"` + Ref string `json:"ref"` // The ref to deploy. This can be a branch, tag, or sha. + Payload interface{} `json:"payload"` + Environment string `json:"environment"` // Name for the target deployment environment. + Task string `json:"task"` // Parameter to specify a task to execute + Created_at string `json:"created_at"` + Original_environment string `json:"original_environment,omitempty"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Id int64 `json:"id"` // Unique identifier of the deployment + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Sha string `json:"sha"` + Description string `json:"description"` + Production_environment bool `json:"production_environment,omitempty"` // Specifies if the given environment is one that end-users directly interact with. Default: false. + Creator GeneratedType `json:"creator"` // A GitHub user. + Statuses_url string `json:"statuses_url"` + Transient_environment bool `json:"transient_environment,omitempty"` // Specifies if the given environment is will no longer exist at some point in the future. Default: false. + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Creator GeneratedType `json:"creator,omitempty"` // A GitHub user. + Node_id string `json:"node_id,omitempty"` + Content_node_id string `json:"content_node_id"` + Id float64 `json:"id"` + Project_node_id string `json:"project_node_id,omitempty"` + Archived_at string `json:"archived_at"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Content_type string `json:"content_type"` // The type of content tracked in a project item +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Personal_access_token_request GeneratedType `json:"personal_access_token_request"` // Details of a Personal Access Token Request. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name pattern that branches must match in order to deploy to the environment. Wildcard characters will not match `/`. For example, to match branches that begin with `release/` and contain an additional single slash, use `release/*/*`. For more information about pattern matching syntax, see the [Ruby File.fnmatch documentation](https://ruby-doc.org/core-2.5.1/File.html#method-c-fnmatch). +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit string `json:"commit"` + Created_at string `json:"created_at"` + Duration int `json:"duration"` + ErrorField map[string]interface{} `json:"error"` + Pusher GeneratedType `json:"pusher"` // A GitHub user. + Status string `json:"status"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request GeneratedType `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id string `json:"id,omitempty"` // An identifier for the upload. + Url string `json:"url,omitempty"` // The REST API URL for checking the status of the upload. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Workflow_run map[string]interface{} `json:"workflow_run,omitempty"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Workflow Webhooksworkflow `json:"workflow,omitempty"` + Deployment map[string]interface{} `json:"deployment"` // The [deployment](https://docs.github.com/rest/deployments/deployments#list-deployments). + Deployment_status map[string]interface{} `json:"deployment_status"` // The [deployment status](https://docs.github.com/rest/deployments/statuses#list-deployment-statuses). + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Check_run map[string]interface{} `json:"check_run,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Completed_at string `json:"completed_at"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Secret_types []string `json:"secret_types,omitempty"` // List of patterns that were updated. This will be empty for normal backfill scans or custom pattern updates + Custom_pattern_scope string `json:"custom_pattern_scope,omitempty"` // If the scan was triggered by a custom pattern update, this will be the scope of the pattern that was updated + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Source string `json:"source"` // What type of content was scanned + Custom_pattern_name string `json:"custom_pattern_name,omitempty"` // If the scan was triggered by a custom pattern update, this will be the name of the pattern that was updated + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Started_at string `json:"started_at"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Action string `json:"action"` + TypeField string `json:"type"` // What type of scan was completed +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_column Webhooksprojectcolumn `json:"project_column"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` // The action that was performed. + Assignee Webhooksusermannequin `json:"assignee,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Requester Webhooksuser `json:"requester,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation Installation `json:"installation"` // Installation + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories []map[string]interface{} `json:"repositories,omitempty"` // An array of repository objects that the installation can access. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Milestone Webhooksmilestone `json:"milestone"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Has_pages bool `json:"has_pages"` + Open_issues_count int `json:"open_issues_count"` + Squash_merge_commit_title string `json:"squash_merge_commit_title,omitempty"` // The default value for a squash merge commit title: - `PR_TITLE` - default to the pull request's title. - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + Tags_url string `json:"tags_url"` + Open_issues int `json:"open_issues"` + Language string `json:"language"` + Topics []string `json:"topics,omitempty"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Forks_count int `json:"forks_count"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Mirror_url string `json:"mirror_url"` + Allow_update_branch bool `json:"allow_update_branch,omitempty"` // Whether or not a pull request head branch that is behind its base branch can always be updated even if it is not required to be up to date before merging. + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Master_branch string `json:"master_branch,omitempty"` + Merges_url string `json:"merges_url"` + Id int64 `json:"id"` // Unique identifier of the repository + Downloads_url string `json:"downloads_url"` + Created_at string `json:"created_at"` + Collaborators_url string `json:"collaborators_url"` + Url string `json:"url"` + Commits_url string `json:"commits_url"` + Squash_merge_commit_message string `json:"squash_merge_commit_message,omitempty"` // The default value for a squash merge commit message: - `PR_BODY` - default to the pull request's body. - `COMMIT_MESSAGES` - default to the branch's commit messages. - `BLANK` - default to a blank commit message. + Statuses_url string `json:"statuses_url"` + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + Owner GeneratedType `json:"owner"` // A GitHub user. + Ssh_url string `json:"ssh_url"` + Blobs_url string `json:"blobs_url"` + Starred_at string `json:"starred_at,omitempty"` + Notifications_url string `json:"notifications_url"` + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` // Whether a squash merge commit can use the pull request title as default. **This property is closing down. Please use `squash_merge_commit_title` instead. + Permissions map[string]interface{} `json:"permissions,omitempty"` + Watchers_count int `json:"watchers_count"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Custom_properties map[string]interface{} `json:"custom_properties,omitempty"` // The custom properties that were defined for the repository. The keys are the custom property names, and the values are the corresponding custom property values. + Keys_url string `json:"keys_url"` + Contributors_url string `json:"contributors_url"` + Homepage string `json:"homepage"` + Contents_url string `json:"contents_url"` + Forks_url string `json:"forks_url"` + Full_name string `json:"full_name"` + Branches_url string `json:"branches_url"` + Git_commits_url string `json:"git_commits_url"` + Node_id string `json:"node_id"` + Private bool `json:"private"` // Whether the repository is private or public. + Comments_url string `json:"comments_url"` + Stargazers_url string `json:"stargazers_url"` + Forks int `json:"forks"` + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Merge_commit_title string `json:"merge_commit_title,omitempty"` // The default value for a merge commit title. - `PR_TITLE` - default to the pull request's title. - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name). + Git_tags_url string `json:"git_tags_url"` + Watchers int `json:"watchers"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Clone_url string `json:"clone_url"` + Pulls_url string `json:"pulls_url"` + Size int `json:"size"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Stargazers_count int `json:"stargazers_count"` + Merge_commit_message string `json:"merge_commit_message,omitempty"` // The default value for a merge commit message. - `PR_TITLE` - default to the pull request's title. - `PR_BODY` - default to the pull request's body. - `BLANK` - default to a blank commit message. + Name string `json:"name"` // The name of the repository. + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + License GeneratedType `json:"license"` // License Simple + Subscription_url string `json:"subscription_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Languages_url string `json:"languages_url"` + Git_url string `json:"git_url"` + Fork bool `json:"fork"` + Template_repository map[string]interface{} `json:"template_repository,omitempty"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Network_count int `json:"network_count,omitempty"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Compare_url string `json:"compare_url"` + Subscribers_url string `json:"subscribers_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Milestones_url string `json:"milestones_url"` + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Events_url string `json:"events_url"` + Trees_url string `json:"trees_url"` + Description string `json:"description"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Html_url string `json:"html_url"` + Issue_comment_url string `json:"issue_comment_url"` + Issues_url string `json:"issues_url"` + Teams_url string `json:"teams_url"` + Hooks_url string `json:"hooks_url"` + Archive_url string `json:"archive_url"` + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Svn_url string `json:"svn_url"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Pushed_at string `json:"pushed_at"` + Assignees_url string `json:"assignees_url"` + Git_refs_url string `json:"git_refs_url"` + Issue_events_url string `json:"issue_events_url"` + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Updated_at string `json:"updated_at"` + Deployments_url string `json:"deployments_url"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub user. + Releases_url string `json:"releases_url"` + Labels_url string `json:"labels_url"` +} + +// Team represents the Team schema from the OpenAPI specification +type Team struct { + Node_id string `json:"node_id"` + Parent GeneratedType `json:"parent"` // Groups of organization members that gives permissions on specified repositories. + Repositories_url string `json:"repositories_url"` + Slug string `json:"slug"` + Description string `json:"description"` + Id int `json:"id"` + Permission string `json:"permission"` + Privacy string `json:"privacy,omitempty"` + Notification_setting string `json:"notification_setting,omitempty"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Html_url string `json:"html_url"` + Name string `json:"name"` + Url string `json:"url"` + Members_url string `json:"members_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enabled bool `json:"enabled"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Remote_id string `json:"remote_id"` + Remote_name string `json:"remote_name"` + Url string `json:"url"` + Email string `json:"email"` + Id int `json:"id"` + Import_url string `json:"import_url"` +} + +// Feed represents the Feed schema from the OpenAPI specification +type Feed struct { + User_url string `json:"user_url"` + Current_user_actor_url string `json:"current_user_actor_url,omitempty"` + Current_user_url string `json:"current_user_url,omitempty"` + Repository_discussions_category_url string `json:"repository_discussions_category_url,omitempty"` // A feed of discussions for a given repository and category. + Links map[string]interface{} `json:"_links"` + Current_user_organization_url string `json:"current_user_organization_url,omitempty"` + Current_user_organization_urls []string `json:"current_user_organization_urls,omitempty"` + Current_user_public_url string `json:"current_user_public_url,omitempty"` + Security_advisories_url string `json:"security_advisories_url,omitempty"` + Repository_discussions_url string `json:"repository_discussions_url,omitempty"` // A feed of discussions for a given repository. + Timeline_url string `json:"timeline_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Source string `json:"source"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sub_issue Issue `json:"sub_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Sub_issue_id float64 `json:"sub_issue_id"` // The ID of the sub-issue. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Parent_issue Issue `json:"parent_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Parent_issue_id float64 `json:"parent_issue_id"` // The ID of the parent issue. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Sub_issue_repo Repository `json:"sub_issue_repo"` // A repository on GitHub. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Personal_access_token_request GeneratedType `json:"personal_access_token_request"` // Details of a Personal Access Token Request. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Payload string `json:"payload"` // A URL-encoded string of the check_run.created JSON payload. The decoded payload is a JSON object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Requester interface{} `json:"requester,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation Installation `json:"installation"` // Installation + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories []map[string]interface{} `json:"repositories,omitempty"` // An array of repository objects that the installation can access. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Start_private_fork bool `json:"start_private_fork,omitempty"` // Whether to create a temporary private fork of the repository to collaborate on a fix. + Summary string `json:"summary"` // A short summary of the advisory. + Vulnerabilities []map[string]interface{} `json:"vulnerabilities,omitempty"` // An array of products affected by the vulnerability detailed in a repository security advisory. + Cvss_vector_string string `json:"cvss_vector_string,omitempty"` // The CVSS vector that calculates the severity of the advisory. You must choose between setting this field or `severity`. + Cwe_ids []string `json:"cwe_ids,omitempty"` // A list of Common Weakness Enumeration (CWE) IDs. + Description string `json:"description"` // A detailed description of what the advisory impacts. + Severity string `json:"severity,omitempty"` // The severity of the advisory. You must choose between setting this field or `cvss_vector_string`. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pusher_type string `json:"pusher_type"` // The pusher type for the event. Can be either `user` or a deploy key. + Ref string `json:"ref"` // The [`git ref`](https://docs.github.com/rest/git/refs#get-a-reference) resource. + Ref_type string `json:"ref_type"` // The type of Git ref object deleted in the repository. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dependency map[string]interface{} `json:"dependency"` // Details for the vulnerable dependency. + Security_vulnerability GeneratedType `json:"security_vulnerability"` // Details pertaining to one vulnerable version range for the advisory. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Auto_dismissed_at string `json:"auto_dismissed_at,omitempty"` // The time that the alert was auto-dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_reason string `json:"dismissed_reason"` // The reason that the alert was dismissed. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Number int `json:"number"` // The security alert number. + Url string `json:"url"` // The REST API URL of the alert resource. + Fixed_at string `json:"fixed_at"` // The time that the alert was no longer detected and was considered fixed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Security_advisory GeneratedType `json:"security_advisory"` // Details for the GitHub Security Advisory. + State string `json:"state"` // The state of the Dependabot alert. + Updated_at string `json:"updated_at"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_comment string `json:"dismissed_comment"` // An optional comment associated with the alert's dismissal. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Permissions GeneratedType `json:"permissions,omitempty"` // The permissions granted to the user access token. + Repositories []Repository `json:"repositories,omitempty"` + Repository_selection string `json:"repository_selection,omitempty"` + Single_file string `json:"single_file,omitempty"` + Single_file_paths []string `json:"single_file_paths,omitempty"` + Token string `json:"token"` + Expires_at string `json:"expires_at"` + Has_multiple_single_files bool `json:"has_multiple_single_files,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Review Webhooksreview `json:"review"` // The review that was affected. + Sender GeneratedType `json:"sender"` // A GitHub user. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Changes map[string]interface{} `json:"changes"` + Pull_request map[string]interface{} `json:"pull_request"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Editors []map[string]interface{} `json:"editors,omitempty"` + Total_engaged_users int `json:"total_engaged_users,omitempty"` // Total number of users who prompted Copilot Chat in the IDE. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Milestone Webhooksmilestone3 `json:"milestone"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + User Webhooksuser `json:"user,omitempty"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Invitation map[string]interface{} `json:"invitation"` // The invitation for the user or email if the action is `member_invited`. +} + +// Project represents the Project schema from the OpenAPI specification +type Project struct { + Id int `json:"id"` + State string `json:"state"` // State of the project; either 'open' or 'closed' + Columns_url string `json:"columns_url"` + Name string `json:"name"` // Name of the project + Body string `json:"body"` // Body of the project + Number int `json:"number"` + Owner_url string `json:"owner_url"` + Private bool `json:"private,omitempty"` // Whether or not this project can be seen by everyone. Only present if owner is an organization. + Updated_at string `json:"updated_at"` + Node_id string `json:"node_id"` + Organization_permission string `json:"organization_permission,omitempty"` // The baseline permission that all organization members have on this project. Only present if owner is an organization. + Creator GeneratedType `json:"creator"` // A GitHub user. + Url string `json:"url"` + Created_at string `json:"created_at"` + Html_url string `json:"html_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Cvss map[string]interface{} `json:"cvss"` + Description string `json:"description"` // A detailed description of what the advisory entails. + Identifiers []map[string]interface{} `json:"identifiers"` + Severity string `json:"severity"` // The severity of the advisory. + Updated_at string `json:"updated_at"` // The date and time of when the advisory was last updated, in ISO 8601 format. + Html_url string `json:"html_url"` // The URL for the advisory. + Summary string `json:"summary"` // A short summary of the advisory. + Url string `json:"url"` // The API URL for the advisory. + Epss GeneratedType `json:"epss,omitempty"` // The EPSS scores as calculated by the [Exploit Prediction Scoring System](https://www.first.org/epss). + Published_at string `json:"published_at"` // The date and time of when the advisory was published, in ISO 8601 format. + Repository_advisory_url string `json:"repository_advisory_url"` // The API URL for the repository advisory. + Nvd_published_at string `json:"nvd_published_at"` // The date and time when the advisory was published in the National Vulnerability Database, in ISO 8601 format. This field is only populated when the advisory is imported from the National Vulnerability Database. + Vulnerabilities []Vulnerability `json:"vulnerabilities"` // The products and respective version ranges affected by the advisory. + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + References []string `json:"references"` + Withdrawn_at string `json:"withdrawn_at"` // The date and time of when the advisory was withdrawn, in ISO 8601 format. + Cve_id string `json:"cve_id"` // The Common Vulnerabilities and Exposures (CVE) ID. + Ghsa_id string `json:"ghsa_id"` // The GitHub Security Advisory ID. + Source_code_location string `json:"source_code_location"` // The URL of the advisory's source code. + Credits []map[string]interface{} `json:"credits"` // The users who contributed to the advisory. + TypeField string `json:"type"` // The type of advisory. + Cwes []map[string]interface{} `json:"cwes"` + Github_reviewed_at string `json:"github_reviewed_at"` // The date and time of when the advisory was reviewed by GitHub, in ISO 8601 format. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url,omitempty"` + Location GeneratedType `json:"location,omitempty"` // Describe a region within a file for the alert. + Analysis_key string `json:"analysis_key,omitempty"` // Identifies the configuration under which the analysis was executed. For example, in GitHub Actions this includes the workflow filename and job name. + State string `json:"state,omitempty"` // State of a code scanning alert. + Message map[string]interface{} `json:"message,omitempty"` + Category string `json:"category,omitempty"` // Identifies the configuration under which the analysis was executed. Used to distinguish between multiple analyses for the same tool and commit, but performed on different languages or different parts of the code. + Commit_sha string `json:"commit_sha,omitempty"` + Ref string `json:"ref,omitempty"` // The Git reference, formatted as `refs/pull//merge`, `refs/pull//head`, `refs/heads/` or simply ``. + Classifications []string `json:"classifications,omitempty"` // Classifications that have been applied to the file that triggered the alert. For example identifying it as documentation, or a generated file. + Environment string `json:"environment,omitempty"` // Identifies the variable values associated with the environment in which the analysis that generated this alert instance was performed, such as the language that was analyzed. +} + +// Reaction represents the Reaction schema from the OpenAPI specification +type Reaction struct { + Node_id string `json:"node_id"` + User GeneratedType `json:"user"` // A GitHub user. + Content string `json:"content"` // The reaction to use + Created_at string `json:"created_at"` + Id int `json:"id"` +} + +// Webhooksrule represents the Webhooksrule schema from the OpenAPI specification +type Webhooksrule struct { + Require_last_push_approval bool `json:"require_last_push_approval,omitempty"` // Whether the most recent push must be approved by someone other than the person who pushed it + Dismiss_stale_reviews_on_push bool `json:"dismiss_stale_reviews_on_push"` + Lock_allows_fork_sync bool `json:"lock_allows_fork_sync,omitempty"` // Whether users can pull changes from upstream when the branch is locked. Set to `true` to allow users to pull changes from upstream when the branch is locked. This setting is only applicable for forks. + Admin_enforced bool `json:"admin_enforced"` + Allow_deletions_enforcement_level string `json:"allow_deletions_enforcement_level"` + Linear_history_requirement_enforcement_level string `json:"linear_history_requirement_enforcement_level"` + Strict_required_status_checks_policy bool `json:"strict_required_status_checks_policy"` + Ignore_approvals_from_contributors bool `json:"ignore_approvals_from_contributors"` + Repository_id int `json:"repository_id"` + Created_at string `json:"created_at"` + Name string `json:"name"` + Create_protected bool `json:"create_protected,omitempty"` + Lock_branch_enforcement_level string `json:"lock_branch_enforcement_level"` // The enforcement level of the branch lock setting. `off` means the branch is not locked, `non_admins` means the branch is read-only for non_admins, and `everyone` means the branch is read-only for everyone. + Signature_requirement_enforcement_level string `json:"signature_requirement_enforcement_level"` + Require_code_owner_review bool `json:"require_code_owner_review"` + Required_status_checks []string `json:"required_status_checks"` + Merge_queue_enforcement_level string `json:"merge_queue_enforcement_level"` + Required_conversation_resolution_level string `json:"required_conversation_resolution_level"` + Required_deployments_enforcement_level string `json:"required_deployments_enforcement_level"` + Id int `json:"id"` + Authorized_actor_names []string `json:"authorized_actor_names"` + Pull_request_reviews_enforcement_level string `json:"pull_request_reviews_enforcement_level"` + Required_approving_review_count int `json:"required_approving_review_count"` + Authorized_dismissal_actors_only bool `json:"authorized_dismissal_actors_only"` + Updated_at string `json:"updated_at"` + Required_status_checks_enforcement_level string `json:"required_status_checks_enforcement_level"` + Allow_force_pushes_enforcement_level string `json:"allow_force_pushes_enforcement_level"` + Authorized_actors_only bool `json:"authorized_actors_only"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` // A Dependabot alert. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Id int `json:"id"` + Required bool `json:"required,omitempty"` + Target_url string `json:"target_url"` + Created_at string `json:"created_at"` + Avatar_url string `json:"avatar_url"` + Url string `json:"url"` + Context string `json:"context"` + Description string `json:"description"` + Node_id string `json:"node_id"` + State string `json:"state"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Event string `json:"event"` + Id int `json:"id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_id string `json:"commit_id"` + Url string `json:"url"` + Created_at string `json:"created_at"` + Label map[string]interface{} `json:"label"` + Node_id string `json:"node_id"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Commit_url string `json:"commit_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Key Webhooksdeploykey `json:"key"` // The [`deploy key`](https://docs.github.com/rest/deploy-keys/deploy-keys#get-a-deploy-key) resource. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Repository_advisory GeneratedType `json:"repository_advisory"` // A repository security advisory. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Author GeneratedType `json:"author"` // A GitHub user. + Total int `json:"total"` + Weeks []map[string]interface{} `json:"weeks"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name,omitempty"` // The name of the workflow run. + Id int `json:"id"` // The ID of the workflow run. + Head_branch string `json:"head_branch"` + Check_suite_id int `json:"check_suite_id,omitempty"` // The ID of the associated check suite. + Status string `json:"status"` + Node_id string `json:"node_id"` + Display_title string `json:"display_title"` // The event-specific title associated with the run or the run-name if set, or the value of `run-name` if it is set in the workflow. + Url string `json:"url"` // The URL to the workflow run. + Run_attempt int `json:"run_attempt,omitempty"` // Attempt number of the run, 1 for first attempt and higher if the workflow was re-run. + Head_commit GeneratedType `json:"head_commit"` // A commit. + Path string `json:"path"` // The full path of the workflow + Html_url string `json:"html_url"` + Check_suite_node_id string `json:"check_suite_node_id,omitempty"` // The node ID of the associated check suite. + Repository GeneratedType `json:"repository"` // Minimal Repository + Triggering_actor GeneratedType `json:"triggering_actor,omitempty"` // A GitHub user. + Pull_requests []GeneratedType `json:"pull_requests"` // Pull requests that are open with a `head_sha` or `head_branch` that matches the workflow run. The returned pull requests do not necessarily indicate pull requests that triggered the run. + Previous_attempt_url string `json:"previous_attempt_url,omitempty"` // The URL to the previous attempted run of this workflow, if one exists. + Head_repository GeneratedType `json:"head_repository"` // Minimal Repository + Conclusion string `json:"conclusion"` + Rerun_url string `json:"rerun_url"` // The URL to rerun the workflow run. + Head_repository_id int `json:"head_repository_id,omitempty"` + Updated_at string `json:"updated_at"` + Artifacts_url string `json:"artifacts_url"` // The URL to the artifacts for the workflow run. + Referenced_workflows []GeneratedType `json:"referenced_workflows,omitempty"` + Event string `json:"event"` + Jobs_url string `json:"jobs_url"` // The URL to the jobs for the workflow run. + Actor GeneratedType `json:"actor,omitempty"` // A GitHub user. + Workflow_url string `json:"workflow_url"` // The URL to the workflow. + Cancel_url string `json:"cancel_url"` // The URL to cancel the workflow run. + Head_sha string `json:"head_sha"` // The SHA of the head commit that points to the version of the workflow being run. + Run_started_at string `json:"run_started_at,omitempty"` // The start time of the latest run. Resets on re-run. + Logs_url string `json:"logs_url"` // The URL to download the logs for the workflow run. + Created_at string `json:"created_at"` + Run_number int `json:"run_number"` // The auto incrementing run number for the workflow run. + Workflow_id int `json:"workflow_id"` // The ID of the parent workflow. + Check_suite_url string `json:"check_suite_url"` // The URL to the associated check suite. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Subscribers_url string `json:"subscribers_url"` // The API URL to list the subscribers on the repository. + Forks_url string `json:"forks_url"` // The API URL to list the forks of the repository. + Hooks_url string `json:"hooks_url"` // The API URL to list the hooks on the repository. + Merges_url string `json:"merges_url"` // The API URL to merge branches in the repository. + Assignees_url string `json:"assignees_url"` // A template for the API URL to list the available assignees for issues in the repository. + Git_refs_url string `json:"git_refs_url"` // A template for the API URL to get information about Git refs of the repository. + Notifications_url string `json:"notifications_url"` // A template for the API URL to get information about notifications on the repository. + Html_url string `json:"html_url"` // The URL to view the repository on GitHub.com. + Commits_url string `json:"commits_url"` // A template for the API URL to get information about commits on the repository. + Name string `json:"name"` // The name of the repository. + Id int64 `json:"id"` // A unique identifier of the repository. + Keys_url string `json:"keys_url"` // A template for the API URL to get information about deploy keys on the repository. + Stargazers_url string `json:"stargazers_url"` // The API URL to list the stargazers on the repository. + Comments_url string `json:"comments_url"` // A template for the API URL to get information about comments on the repository. + Downloads_url string `json:"downloads_url"` // The API URL to list the downloads on the repository. + Trees_url string `json:"trees_url"` // A template for the API URL to create or retrieve a raw Git tree of the repository. + Contributors_url string `json:"contributors_url"` // A template for the API URL to list the contributors to the repository. + Fork bool `json:"fork"` // Whether the repository is a fork. + Issues_url string `json:"issues_url"` // A template for the API URL to get information about issues on the repository. + Node_id string `json:"node_id"` // The GraphQL identifier of the repository. + Releases_url string `json:"releases_url"` // A template for the API URL to get information about releases on the repository. + Archive_url string `json:"archive_url"` // A template for the API URL to download the repository as an archive. + Tags_url string `json:"tags_url"` // The API URL to get information about tags on the repository. + Languages_url string `json:"languages_url"` // The API URL to get information about the languages of the repository. + Issue_events_url string `json:"issue_events_url"` // A template for the API URL to get information about issue events on the repository. + Issue_comment_url string `json:"issue_comment_url"` // A template for the API URL to get information about issue comments on the repository. + Statuses_url string `json:"statuses_url"` // A template for the API URL to get information about statuses of a commit. + Deployments_url string `json:"deployments_url"` // The API URL to list the deployments of the repository. + Teams_url string `json:"teams_url"` // The API URL to list the teams on the repository. + Contents_url string `json:"contents_url"` // A template for the API URL to get the contents of the repository. + Events_url string `json:"events_url"` // The API URL to list the events of the repository. + Full_name string `json:"full_name"` // The full, globally unique, name of the repository. + Milestones_url string `json:"milestones_url"` // A template for the API URL to get information about milestones of the repository. + Subscription_url string `json:"subscription_url"` // The API URL to subscribe to notifications for this repository. + Branches_url string `json:"branches_url"` // A template for the API URL to get information about branches in the repository. + Git_tags_url string `json:"git_tags_url"` // A template for the API URL to get information about Git tags of the repository. + Git_commits_url string `json:"git_commits_url"` // A template for the API URL to get information about Git commits of the repository. + Description string `json:"description"` // The repository description. + Url string `json:"url"` // The URL to get more information about the repository from the GitHub API. + Collaborators_url string `json:"collaborators_url"` // A template for the API URL to get information about collaborators of the repository. + Pulls_url string `json:"pulls_url"` // A template for the API URL to get information about pull requests on the repository. + Owner GeneratedType `json:"owner"` // A GitHub user. + Blobs_url string `json:"blobs_url"` // A template for the API URL to create or retrieve a raw Git blob in the repository. + Labels_url string `json:"labels_url"` // A template for the API URL to get information about labels of the repository. + Private bool `json:"private"` // Whether the repository is private. + Compare_url string `json:"compare_url"` // A template for the API URL to compare two commits or refs. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Private bool `json:"private"` // Whether the repository is private. + Default_branch string `json:"default_branch"` // The default branch for the repository. + Full_name string `json:"full_name"` // The full, globally unique name of the repository. + Html_url string `json:"html_url"` // The URL to view the repository on GitHub.com. + Id int `json:"id"` // A unique identifier of the repository. + Node_id string `json:"node_id"` // The GraphQL identifier of the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at,omitempty"` // The time the issue type created. + Description string `json:"description"` // The description of the issue type. + Id int `json:"id"` // The unique identifier of the issue type. + Is_enabled bool `json:"is_enabled,omitempty"` // The enabled state of the issue type. + Name string `json:"name"` // The name of the issue type. + Node_id string `json:"node_id"` // The node identifier of the issue type. + Updated_at string `json:"updated_at,omitempty"` // The time the issue type last updated. + Color string `json:"color,omitempty"` // The color of the issue type. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project Webhooksproject `json:"project"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` // The changes to the project if the action was `edited`. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ref_name map[string]interface{} `json:"ref_name,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Body_html string `json:"body_html,omitempty"` + Body_text string `json:"body_text,omitempty"` + Links map[string]interface{} `json:"_links"` + Html_url string `json:"html_url"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Body string `json:"body"` + Original_commit_id string `json:"original_commit_id"` + Commit_id string `json:"commit_id"` + In_reply_to_id int `json:"in_reply_to_id,omitempty"` + Id int64 `json:"id"` + Original_position int `json:"original_position"` + Original_start_line int `json:"original_start_line,omitempty"` // The original first line of the range for a multi-line comment. + Start_side string `json:"start_side,omitempty"` // The side of the first line of the range for a multi-line comment. + Pull_request_review_id int64 `json:"pull_request_review_id"` + Pull_request_url string `json:"pull_request_url"` + User GeneratedType `json:"user"` // A GitHub user. + Position int `json:"position"` + Path string `json:"path"` + Reactions GeneratedType `json:"reactions,omitempty"` + Start_line int `json:"start_line,omitempty"` // The first line of the range for a multi-line comment. + Node_id string `json:"node_id"` + Subject_type string `json:"subject_type,omitempty"` // The level at which the comment is targeted, can be a diff line or a file. + Side string `json:"side,omitempty"` // The side of the first line of the range for a multi-line comment. + Diff_hunk string `json:"diff_hunk"` + Original_line int `json:"original_line,omitempty"` // The original line of the blob to which the comment applies. The last line of the range for a multi-line comment + Author_association string `json:"author_association"` // How the author is associated with the repository. + Updated_at string `json:"updated_at"` + Line int `json:"line,omitempty"` // The line of the blob to which the comment applies. The last line of the range for a multi-line comment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Comment Webhooksreviewcomment `json:"comment"` // The [comment](https://docs.github.com/rest/pulls/comments#get-a-review-comment-for-a-pull-request) itself. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the variable. + Updated_at string `json:"updated_at"` // The date and time at which the variable was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Value string `json:"value"` // The value of the variable. + Created_at string `json:"created_at"` // The date and time at which the variable was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Commit_url string `json:"commit_url"` + Event string `json:"event"` + Id int `json:"id"` + Url string `json:"url"` + Commit_id string `json:"commit_id"` + Created_at string `json:"created_at"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Project_card map[string]interface{} `json:"project_card,omitempty"` + Actor GeneratedType `json:"actor"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Url string `json:"url"` + Has_issues bool `json:"has_issues,omitempty"` + Security_and_analysis GeneratedType `json:"security_and_analysis,omitempty"` + Is_template bool `json:"is_template,omitempty"` + Updated_at string `json:"updated_at,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Notifications_url string `json:"notifications_url"` + Has_projects bool `json:"has_projects,omitempty"` + Git_tags_url string `json:"git_tags_url"` + Languages_url string `json:"languages_url"` + Git_commits_url string `json:"git_commits_url"` + Pulls_url string `json:"pulls_url"` + Downloads_url string `json:"downloads_url"` + Tags_url string `json:"tags_url"` + Visibility string `json:"visibility,omitempty"` + Teams_url string `json:"teams_url"` + Network_count int `json:"network_count,omitempty"` + Has_wiki bool `json:"has_wiki,omitempty"` + Default_branch string `json:"default_branch,omitempty"` + Events_url string `json:"events_url"` + Contents_url string `json:"contents_url"` + Svn_url string `json:"svn_url,omitempty"` + Pushed_at string `json:"pushed_at,omitempty"` + Keys_url string `json:"keys_url"` + Has_discussions bool `json:"has_discussions,omitempty"` + Mirror_url string `json:"mirror_url,omitempty"` + Git_refs_url string `json:"git_refs_url"` + Language string `json:"language,omitempty"` + Stargazers_count int `json:"stargazers_count,omitempty"` + Open_issues_count int `json:"open_issues_count,omitempty"` + Releases_url string `json:"releases_url"` + Role_name string `json:"role_name,omitempty"` + License map[string]interface{} `json:"license,omitempty"` + Milestones_url string `json:"milestones_url"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Collaborators_url string `json:"collaborators_url"` + Git_url string `json:"git_url,omitempty"` + Assignees_url string `json:"assignees_url"` + Forks_url string `json:"forks_url"` + Deployments_url string `json:"deployments_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Code_of_conduct GeneratedType `json:"code_of_conduct,omitempty"` // Code Of Conduct + Topics []string `json:"topics,omitempty"` + Created_at string `json:"created_at,omitempty"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Full_name string `json:"full_name"` + Issue_events_url string `json:"issue_events_url"` + Commits_url string `json:"commits_url"` + Branches_url string `json:"branches_url"` + Description string `json:"description"` + Statuses_url string `json:"statuses_url"` + Ssh_url string `json:"ssh_url,omitempty"` + Blobs_url string `json:"blobs_url"` + Contributors_url string `json:"contributors_url"` + Forks int `json:"forks,omitempty"` + Clone_url string `json:"clone_url,omitempty"` + Open_issues int `json:"open_issues,omitempty"` + Watchers_count int `json:"watchers_count,omitempty"` + Private bool `json:"private"` + Id int64 `json:"id"` + Fork bool `json:"fork"` + Hooks_url string `json:"hooks_url"` + Compare_url string `json:"compare_url"` + Html_url string `json:"html_url"` + Homepage string `json:"homepage,omitempty"` + Allow_forking bool `json:"allow_forking,omitempty"` + Size int `json:"size,omitempty"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Permissions map[string]interface{} `json:"permissions,omitempty"` + Has_downloads bool `json:"has_downloads,omitempty"` + Watchers int `json:"watchers,omitempty"` + Trees_url string `json:"trees_url"` + Subscribers_url string `json:"subscribers_url"` + Archive_url string `json:"archive_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Archived bool `json:"archived,omitempty"` + Comments_url string `json:"comments_url"` + Stargazers_url string `json:"stargazers_url"` + Node_id string `json:"node_id"` + Issues_url string `json:"issues_url"` + Merges_url string `json:"merges_url"` + Subscription_url string `json:"subscription_url"` + Issue_comment_url string `json:"issue_comment_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Has_pages bool `json:"has_pages,omitempty"` + Forks_count int `json:"forks_count,omitempty"` + Custom_properties map[string]interface{} `json:"custom_properties,omitempty"` // The custom properties that were defined for the repository. The keys are the custom property names, and the values are the corresponding custom property values. + Labels_url string `json:"labels_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// Key represents the Key schema from the OpenAPI specification +type Key struct { + Created_at string `json:"created_at"` + Id int64 `json:"id"` + Key string `json:"key"` + Read_only bool `json:"read_only"` + Title string `json:"title"` + Url string `json:"url"` + Verified bool `json:"verified"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Old_answer Webhooksanswer `json:"old_answer"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository map[string]interface{} `json:"repository,omitempty"` // A git repository + Sender GeneratedType `json:"sender"` // A GitHub user. + Team Webhooksteam1 `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow_run map[string]interface{} `json:"workflow_run"` + Action string `json:"action"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Deployment map[string]interface{} `json:"deployment"` // The [deployment](https://docs.github.com/rest/deployments/deployments#list-deployments). + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Workflow Webhooksworkflow `json:"workflow"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Number int `json:"number"` // The pull request number. + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Assignee Webhooksuser `json:"assignee"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor GeneratedType `json:"actor,omitempty"` // A GitHub user. + Created_at string `json:"created_at"` + Event string `json:"event"` + Source map[string]interface{} `json:"source"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Total_active_caches_size_in_bytes int `json:"total_active_caches_size_in_bytes"` // The total size in bytes of all active cache items across all repositories of an enterprise or an organization. + Total_active_caches_count int `json:"total_active_caches_count"` // The count of active caches across all repositories of an enterprise or an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Duration float64 `json:"duration,omitempty"` + Id string `json:"id"` + Start_date string `json:"start_date,omitempty"` + Title string `json:"title"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit_oid string `json:"commit_oid"` // The commit SHA of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Action string `json:"action"` + Ref string `json:"ref"` // The Git reference of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes,omitempty"` // The changes to the label if the action was `edited`. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Label Webhookslabel `json:"label"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Key string `json:"key"` // The Base64 encoded public key. + Key_id string `json:"key_id"` // The identifier for the key. + Title string `json:"title,omitempty"` + Url string `json:"url,omitempty"` + Created_at string `json:"created_at,omitempty"` + Id int `json:"id,omitempty"` +} + +// Manifest represents the Manifest schema from the OpenAPI specification +type Manifest struct { + Metadata Metadata `json:"metadata,omitempty"` // User-defined metadata to store domain-specific information limited to 8 keys with scalar values. + Name string `json:"name"` // The name of the manifest. + Resolved map[string]interface{} `json:"resolved,omitempty"` // A collection of resolved package dependencies. + File map[string]interface{} `json:"file,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sha string `json:"sha"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2 GeneratedType `json:"projects_v2"` // A projects v2 project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Assignment GeneratedType `json:"assignment"` // A GitHub Classroom assignment + Commit_count int `json:"commit_count"` // Count of student commits. + Grade string `json:"grade"` // Most recent grade. + Id int `json:"id"` // Unique identifier of the repository. + Passing bool `json:"passing"` // Whether a submission passed. + Repository GeneratedType `json:"repository"` // A GitHub repository view for Classroom + Students []GeneratedType `json:"students"` + Submitted bool `json:"submitted"` // Whether an accepted assignment has been submitted. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Preferences map[string]interface{} `json:"preferences"` + Repository GeneratedType `json:"repository"` // Minimal Repository +} + +// Webhookslabel represents the Webhookslabel schema from the OpenAPI specification +type Webhookslabel struct { + Description string `json:"description"` + Id int `json:"id"` + Name string `json:"name"` // The name of the label. + Node_id string `json:"node_id"` + Url string `json:"url"` // URL for the label + Color string `json:"color"` // 6-character hex code, without the leading #, identifying the color + DefaultField bool `json:"default"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Blocked_user Webhooksuser `json:"blocked_user"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// Repository represents the Repository schema from the OpenAPI specification +type Repository struct { + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + License GeneratedType `json:"license"` // License Simple + Topics []string `json:"topics,omitempty"` + Branches_url string `json:"branches_url"` + Size int `json:"size"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Allow_update_branch bool `json:"allow_update_branch,omitempty"` // Whether or not a pull request head branch that is behind its base branch can always be updated even if it is not required to be up to date before merging. + Full_name string `json:"full_name"` + Squash_merge_commit_message string `json:"squash_merge_commit_message,omitempty"` // The default value for a squash merge commit message: - `PR_BODY` - default to the pull request's body. - `COMMIT_MESSAGES` - default to the branch's commit messages. - `BLANK` - default to a blank commit message. + Merge_commit_title string `json:"merge_commit_title,omitempty"` // The default value for a merge commit title. - `PR_TITLE` - default to the pull request's title. - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name). + Pulls_url string `json:"pulls_url"` + Teams_url string `json:"teams_url"` + Has_pages bool `json:"has_pages"` + Private bool `json:"private"` // Whether the repository is private or public. + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Node_id string `json:"node_id"` + Git_tags_url string `json:"git_tags_url"` + Ssh_url string `json:"ssh_url"` + Deployments_url string `json:"deployments_url"` + Issue_events_url string `json:"issue_events_url"` + Assignees_url string `json:"assignees_url"` + Contents_url string `json:"contents_url"` + Issues_url string `json:"issues_url"` + Forks_url string `json:"forks_url"` + Contributors_url string `json:"contributors_url"` + Hooks_url string `json:"hooks_url"` + Trees_url string `json:"trees_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Mirror_url string `json:"mirror_url"` + Svn_url string `json:"svn_url"` + Html_url string `json:"html_url"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Subscription_url string `json:"subscription_url"` + Events_url string `json:"events_url"` + Clone_url string `json:"clone_url"` + Keys_url string `json:"keys_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Archived bool `json:"archived"` // Whether the repository is archived. + Watchers_count int `json:"watchers_count"` + Forks_count int `json:"forks_count"` + Notifications_url string `json:"notifications_url"` + Homepage string `json:"homepage"` + Code_search_index_status map[string]interface{} `json:"code_search_index_status,omitempty"` // The status of the code search index for this repository + Collaborators_url string `json:"collaborators_url"` + Merges_url string `json:"merges_url"` + Name string `json:"name"` // The name of the repository. + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Git_url string `json:"git_url"` + Squash_merge_commit_title string `json:"squash_merge_commit_title,omitempty"` // The default value for a squash merge commit title: - `PR_TITLE` - default to the pull request's title. - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + Merge_commit_message string `json:"merge_commit_message,omitempty"` // The default value for a merge commit message. - `PR_TITLE` - default to the pull request's title. - `PR_BODY` - default to the pull request's body. - `BLANK` - default to a blank commit message. + Compare_url string `json:"compare_url"` + Statuses_url string `json:"statuses_url"` + Git_refs_url string `json:"git_refs_url"` + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` // Whether a squash merge commit can use the pull request title as default. **This property is closing down. Please use `squash_merge_commit_title` instead. + Watchers int `json:"watchers"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Id int64 `json:"id"` // Unique identifier of the repository + Tags_url string `json:"tags_url"` + Languages_url string `json:"languages_url"` + Milestones_url string `json:"milestones_url"` + Issue_comment_url string `json:"issue_comment_url"` + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Labels_url string `json:"labels_url"` + Url string `json:"url"` + Updated_at string `json:"updated_at"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Stargazers_count int `json:"stargazers_count"` + Created_at string `json:"created_at"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Forks int `json:"forks"` + Open_issues int `json:"open_issues"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Language string `json:"language"` + Comments_url string `json:"comments_url"` + Fork bool `json:"fork"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Permissions map[string]interface{} `json:"permissions,omitempty"` + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Description string `json:"description"` + Commits_url string `json:"commits_url"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Stargazers_url string `json:"stargazers_url"` + Subscribers_url string `json:"subscribers_url"` + Archive_url string `json:"archive_url"` + Downloads_url string `json:"downloads_url"` + Open_issues_count int `json:"open_issues_count"` + Git_commits_url string `json:"git_commits_url"` + Master_branch string `json:"master_branch,omitempty"` + Releases_url string `json:"releases_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Blobs_url string `json:"blobs_url"` + Starred_at string `json:"starred_at,omitempty"` + Pushed_at string `json:"pushed_at"` +} + +// Migration represents the Migration schema from the OpenAPI specification +type Migration struct { + Url string `json:"url"` + Exclude []string `json:"exclude,omitempty"` // Exclude related items from being returned in the response in order to improve performance of the request. The array can include any of: `"repositories"`. + Exclude_releases bool `json:"exclude_releases"` + Updated_at string `json:"updated_at"` + Node_id string `json:"node_id"` + Org_metadata_only bool `json:"org_metadata_only"` + Exclude_attachments bool `json:"exclude_attachments"` + State string `json:"state"` + Repositories []Repository `json:"repositories"` // The repositories included in the migration. Only returned for export migrations. + Exclude_metadata bool `json:"exclude_metadata"` + Id int64 `json:"id"` + Lock_repositories bool `json:"lock_repositories"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Created_at string `json:"created_at"` + Exclude_git_data bool `json:"exclude_git_data"` + Archive_url string `json:"archive_url,omitempty"` + Exclude_owner_projects bool `json:"exclude_owner_projects"` + Guid string `json:"guid"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Membership Webhooksmembership `json:"membership"` // The membership between the user and the organization. Not present when the action is `member_invited`. + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// Label represents the Label schema from the OpenAPI specification +type Label struct { + Color string `json:"color"` // 6-character hex code, without the leading #, identifying the color + DefaultField bool `json:"default"` // Whether this label comes by default in a new repository. + Description string `json:"description"` // Optional description of the label, such as its purpose. + Id int64 `json:"id"` // Unique identifier for the label. + Name string `json:"name"` // The name of the label. + Node_id string `json:"node_id"` + Url string `json:"url"` // URL for the label +} + +// Webhookspullrequest5 represents the Webhookspullrequest5 schema from the OpenAPI specification +type Webhookspullrequest5 struct { + Maintainer_can_modify bool `json:"maintainer_can_modify,omitempty"` // Indicates whether maintainers can modify the pull request. + Merged_at string `json:"merged_at"` + Auto_merge map[string]interface{} `json:"auto_merge"` // The status of auto merging a pull request. + Changed_files int `json:"changed_files,omitempty"` + Issue_url string `json:"issue_url"` + Commits_url string `json:"commits_url"` + Node_id string `json:"node_id"` + Closed_at string `json:"closed_at"` + Comments int `json:"comments,omitempty"` + Requested_reviewers []interface{} `json:"requested_reviewers"` + Updated_at string `json:"updated_at"` + Requested_teams []map[string]interface{} `json:"requested_teams"` + Url string `json:"url"` + Comments_url string `json:"comments_url"` + Milestone map[string]interface{} `json:"milestone"` // A collection of related issues and pull requests. + Id int `json:"id"` + Statuses_url string `json:"statuses_url"` + Html_url string `json:"html_url"` + Additions int `json:"additions,omitempty"` + Review_comments int `json:"review_comments,omitempty"` + Base map[string]interface{} `json:"base"` + Locked bool `json:"locked"` + Merged_by map[string]interface{} `json:"merged_by,omitempty"` + Diff_url string `json:"diff_url"` + Assignee map[string]interface{} `json:"assignee"` + Patch_url string `json:"patch_url"` + Review_comment_url string `json:"review_comment_url"` + Review_comments_url string `json:"review_comments_url"` + Links map[string]interface{} `json:"_links"` + Draft bool `json:"draft"` // Indicates whether or not the pull request is a draft. + Number int `json:"number"` // Number uniquely identifying the pull request within its repository. + Deletions int `json:"deletions,omitempty"` + Merged bool `json:"merged,omitempty"` + State string `json:"state"` // State of this Pull Request. Either `open` or `closed`. + Mergeable bool `json:"mergeable,omitempty"` + User map[string]interface{} `json:"user"` + Title string `json:"title"` // The title of the pull request. + Commits int `json:"commits,omitempty"` + Rebaseable bool `json:"rebaseable,omitempty"` + Body string `json:"body"` + Created_at string `json:"created_at"` + Assignees []map[string]interface{} `json:"assignees"` + Merge_commit_sha string `json:"merge_commit_sha"` + Mergeable_state string `json:"mergeable_state,omitempty"` + Labels []map[string]interface{} `json:"labels"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Active_lock_reason string `json:"active_lock_reason"` + Head map[string]interface{} `json:"head"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Path string `json:"path"` + Ref string `json:"ref,omitempty"` + Sha string `json:"sha"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Committed_at string `json:"committed_at,omitempty"` + Url string `json:"url,omitempty"` + User GeneratedType `json:"user,omitempty"` // A GitHub user. + Version string `json:"version,omitempty"` + Change_status map[string]interface{} `json:"change_status,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + PackageField map[string]interface{} `json:"package"` // The name of the package affected by the vulnerability. + Patched_versions string `json:"patched_versions"` // The package version(s) that resolve the vulnerability. + Vulnerable_functions []string `json:"vulnerable_functions"` // The functions in the package that are affected. + Vulnerable_version_range string `json:"vulnerable_version_range"` // The range of the package versions affected by the vulnerability. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Sponsorship Webhookssponsorship `json:"sponsorship"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Event string `json:"event"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Node_id string `json:"node_id"` + Commit_id string `json:"commit_id"` + Id int `json:"id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + State string `json:"state"` // The state of the user's acceptance of the credit. + TypeField string `json:"type"` // The type of credit the user is receiving. + User GeneratedType `json:"user"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Confirm_delete_url string `json:"confirm_delete_url"` // Next deletable analysis in chain, with last analysis deletion confirmation + Next_analysis_url string `json:"next_analysis_url"` // Next deletable analysis in chain, without last analysis deletion confirmation +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Status string `json:"status"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Allow_force_pushes map[string]interface{} `json:"allow_force_pushes,omitempty"` + Protection_url string `json:"protection_url,omitempty"` + Url string `json:"url,omitempty"` + Allow_fork_syncing map[string]interface{} `json:"allow_fork_syncing,omitempty"` // Whether users can pull changes from upstream when the branch is locked. Set to `true` to allow fork syncing. Set to `false` to prevent fork syncing. + Required_pull_request_reviews GeneratedType `json:"required_pull_request_reviews,omitempty"` // Protected Branch Pull Request Review + Required_status_checks GeneratedType `json:"required_status_checks,omitempty"` // Protected Branch Required Status Check + Required_conversation_resolution map[string]interface{} `json:"required_conversation_resolution,omitempty"` + Name string `json:"name,omitempty"` + Allow_deletions map[string]interface{} `json:"allow_deletions,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Lock_branch map[string]interface{} `json:"lock_branch,omitempty"` // Whether to set the branch as read-only. If this is true, users will not be able to push to the branch. + Required_signatures map[string]interface{} `json:"required_signatures,omitempty"` + Enforce_admins GeneratedType `json:"enforce_admins,omitempty"` // Protected Branch Admin Enforced + Restrictions GeneratedType `json:"restrictions,omitempty"` // Branch Restriction Policy + Block_creations map[string]interface{} `json:"block_creations,omitempty"` + Required_linear_history map[string]interface{} `json:"required_linear_history,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Severity string `json:"severity"` // The severity of the advisory. + State string `json:"state"` // The state of the advisory. + Credits_detailed []GeneratedType `json:"credits_detailed"` + Withdrawn_at string `json:"withdrawn_at"` // The date and time of when the advisory was withdrawn, in ISO 8601 format. + Collaborating_teams []Team `json:"collaborating_teams"` // A list of teams that collaborate on the advisory. + Cve_id string `json:"cve_id"` // The Common Vulnerabilities and Exposures (CVE) ID. + Submission map[string]interface{} `json:"submission"` + Credits []map[string]interface{} `json:"credits"` + Description string `json:"description"` // A detailed description of what the advisory entails. + Author interface{} `json:"author"` // The author of the advisory. + Html_url string `json:"html_url"` // The URL for the advisory. + Ghsa_id string `json:"ghsa_id"` // The GitHub Security Advisory ID. + Closed_at string `json:"closed_at"` // The date and time of when the advisory was closed, in ISO 8601 format. + Collaborating_users []GeneratedType `json:"collaborating_users"` // A list of users that collaborate on the advisory. + Created_at string `json:"created_at"` // The date and time of when the advisory was created, in ISO 8601 format. + Cwe_ids []string `json:"cwe_ids"` // A list of only the CWE IDs. + Private_fork interface{} `json:"private_fork"` // A temporary private fork of the advisory's repository for collaborating on a fix. + Summary string `json:"summary"` // A short summary of the advisory. + Updated_at string `json:"updated_at"` // The date and time of when the advisory was last updated, in ISO 8601 format. + Cvss map[string]interface{} `json:"cvss"` + Publisher interface{} `json:"publisher"` // The publisher of the advisory. + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + Url string `json:"url"` // The API URL for the advisory. + Vulnerabilities []GeneratedType `json:"vulnerabilities"` + Published_at string `json:"published_at"` // The date and time of when the advisory was published, in ISO 8601 format. + Cwes []map[string]interface{} `json:"cwes"` + Identifiers []map[string]interface{} `json:"identifiers"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Backfill_scans []GeneratedType `json:"backfill_scans,omitempty"` + Custom_pattern_backfill_scans []interface{} `json:"custom_pattern_backfill_scans,omitempty"` + Incremental_scans []GeneratedType `json:"incremental_scans,omitempty"` + Pattern_update_scans []GeneratedType `json:"pattern_update_scans,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Since string `json:"since"` + Action string `json:"action"` + Environment string `json:"environment"` + Reviewers []map[string]interface{} `json:"reviewers"` + Workflow_job_run map[string]interface{} `json:"workflow_job_run"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Requestor Webhooksuser `json:"requestor"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Workflow_run map[string]interface{} `json:"workflow_run"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Deliveries_url string `json:"deliveries_url,omitempty"` + Events []string `json:"events"` + Id int `json:"id"` + Name string `json:"name"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Ping_url string `json:"ping_url"` + Active bool `json:"active"` + Config map[string]interface{} `json:"config"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enforcement_level string `json:"enforcement_level,omitempty"` + Strict bool `json:"strict,omitempty"` + Url string `json:"url,omitempty"` + Checks []map[string]interface{} `json:"checks"` + Contexts []string `json:"contexts"` + Contexts_url string `json:"contexts_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + User GeneratedType `json:"user"` // A GitHub user. + Author_association string `json:"author_association"` // How the author is associated with the repository. + Body string `json:"body"` // The text of the review. + Body_text string `json:"body_text,omitempty"` + Node_id string `json:"node_id"` + Body_html string `json:"body_html,omitempty"` + Commit_id string `json:"commit_id"` // A commit SHA for the review. If the commit object was garbage collected or forcibly deleted, then it no longer exists in Git and this value will be `null`. + Html_url string `json:"html_url"` + Links map[string]interface{} `json:"_links"` + Id int64 `json:"id"` // Unique identifier of the review + Submitted_at string `json:"submitted_at,omitempty"` + Pull_request_url string `json:"pull_request_url"` + State string `json:"state"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Definition GeneratedType `json:"definition"` // Custom property defined on an organization + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Raw_details string `json:"raw_details"` + Start_line int `json:"start_line"` + End_column int `json:"end_column"` + Message string `json:"message"` + Blob_href string `json:"blob_href"` + Title string `json:"title"` + Annotation_level string `json:"annotation_level"` + Path string `json:"path"` + Start_column int `json:"start_column"` + End_line int `json:"end_line"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Roster_identifier string `json:"roster_identifier"` // Roster identifier of the student + Student_repository_url string `json:"student_repository_url"` // URL of the student's assignment repository + Assignment_name string `json:"assignment_name"` // Name of the assignment + Points_available int `json:"points_available"` // Number of points available for the assignment + Starter_code_url string `json:"starter_code_url"` // URL of the starter code for the assignment + Submission_timestamp string `json:"submission_timestamp"` // Timestamp of the student's assignment submission + Points_awarded int `json:"points_awarded"` // Number of points awarded to the student + Assignment_url string `json:"assignment_url"` // URL of the assignment + Github_username string `json:"github_username"` // GitHub username of the student + Student_repository_name string `json:"student_repository_name"` // Name of the student's assignment repository + Group_name string `json:"group_name,omitempty"` // If a group assignment, name of the group the student is in +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Checks []map[string]interface{} `json:"checks"` + Contexts []string `json:"contexts"` + Contexts_url string `json:"contexts_url"` + Strict bool `json:"strict"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor GeneratedType `json:"actor"` // A GitHub user. + Event string `json:"event"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Commit_url string `json:"commit_url"` + Project_card map[string]interface{} `json:"project_card,omitempty"` + Commit_id string `json:"commit_id"` + Url string `json:"url"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Visibility string `json:"visibility"` // Visibility of a secret + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. + Selected_repositories_url string `json:"selected_repositories_url,omitempty"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Account interface{} `json:"account"` + Created_at string `json:"created_at"` + Id int `json:"id"` // Unique identifier of the request installation. + Node_id string `json:"node_id,omitempty"` + Requester GeneratedType `json:"requester"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Membership Webhooksmembership `json:"membership,omitempty"` // The membership between the user and the organization. Not present when the action is `member_invited`. + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// Webhookssecurityadvisory represents the Webhookssecurityadvisory schema from the OpenAPI specification +type Webhookssecurityadvisory struct { + Published_at string `json:"published_at"` + References []map[string]interface{} `json:"references"` + Updated_at string `json:"updated_at"` + Cvss map[string]interface{} `json:"cvss"` + Cwes []map[string]interface{} `json:"cwes"` + Identifiers []map[string]interface{} `json:"identifiers"` + Severity string `json:"severity"` + Summary string `json:"summary"` + Vulnerabilities []map[string]interface{} `json:"vulnerabilities"` + Withdrawn_at string `json:"withdrawn_at"` + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + Description string `json:"description"` + Ghsa_id string `json:"ghsa_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Comments []GeneratedType `json:"comments,omitempty"` + Event string `json:"event,omitempty"` + Node_id string `json:"node_id,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit_url string `json:"commit_url"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Id int `json:"id"` + Node_id string `json:"node_id"` + Requested_reviewer GeneratedType `json:"requested_reviewer,omitempty"` // A GitHub user. + Review_requester GeneratedType `json:"review_requester"` // A GitHub user. + Commit_id string `json:"commit_id"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Requested_team Team `json:"requested_team,omitempty"` // Groups of organization members that gives permissions on specified repositories. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. +} + +// Webhooksuser represents the Webhooksuser schema from the OpenAPI specification +type Webhooksuser struct { + Id int64 `json:"id"` + Repos_url string `json:"repos_url,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Events_url string `json:"events_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Login string `json:"login"` + Deleted bool `json:"deleted,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + Email string `json:"email,omitempty"` + Followers_url string `json:"followers_url,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + Name string `json:"name,omitempty"` + Gists_url string `json:"gists_url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Url string `json:"url,omitempty"` + TypeField string `json:"type,omitempty"` +} + +// Autolink represents the Autolink schema from the OpenAPI specification +type Autolink struct { + Id int `json:"id"` + Is_alphanumeric bool `json:"is_alphanumeric"` // Whether this autolink reference matches alphanumeric characters. If false, this autolink reference only matches numeric characters. + Key_prefix string `json:"key_prefix"` // The prefix of a key that is linkified. + Url_template string `json:"url_template"` // A template for the target URL that is generated if a key was found. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Release Webhooksrelease `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project Webhooksproject `json:"project"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert Webhooksalert `json:"alert"` // The security alert of the vulnerable dependency. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Run_duration_ms int `json:"run_duration_ms,omitempty"` + Billable map[string]interface{} `json:"billable"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Original_environment string `json:"original_environment,omitempty"` + Node_id string `json:"node_id"` + Task string `json:"task"` // Parameter to specify a task to execute + Updated_at string `json:"updated_at"` + Production_environment bool `json:"production_environment,omitempty"` // Specifies if the given environment is one that end-users directly interact with. Default: false. + Repository_url string `json:"repository_url"` + Url string `json:"url"` + Created_at string `json:"created_at"` + Description string `json:"description"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Statuses_url string `json:"statuses_url"` + Transient_environment bool `json:"transient_environment,omitempty"` // Specifies if the given environment is will no longer exist at some point in the future. Default: false. + Environment string `json:"environment"` // Name for the target deployment environment. + Id int `json:"id"` // Unique identifier of the deployment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action,omitempty"` + Check_run GeneratedType `json:"check_run"` // A check performed on the code of a given code change + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Key string `json:"key"` + Name string `json:"name"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` // ID of the reviewer which must review changes to matching files. + TypeField string `json:"type"` // The type of the reviewer +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Environments []map[string]interface{} `json:"environments"` // The list of environments that were approved or rejected + State string `json:"state"` // Whether deployment to the environment(s) was approved or rejected or pending (with comments) + User GeneratedType `json:"user"` // A GitHub user. + Comment string `json:"comment"` // The comment submitted with the deployment review +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Personal_access_token_request GeneratedType `json:"personal_access_token_request"` // Details of a Personal Access Token Request. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Release map[string]interface{} `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_column Webhooksprojectcolumn `json:"project_column"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Label Webhookslabel `json:"label,omitempty"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Include_claim_keys []string `json:"include_claim_keys"` // Array of unique strings. Each claim key can only contain alphanumeric characters and underscores. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Check_suite map[string]interface{} `json:"check_suite"` // The [check_suite](https://docs.github.com/rest/checks/suites#get-a-check-suite). + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Runner_type string `json:"runner_type,omitempty"` // Whether to use labeled runners or standard GitHub runners. + Runner_label string `json:"runner_label,omitempty"` // The label of the runner to use for code scanning default setup when runner_type is 'labeled'. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int64 `json:"id"` + Url string `json:"url"` + Login string `json:"login"` + Organizations_url string `json:"organizations_url"` + Email string `json:"email,omitempty"` + Events_url string `json:"events_url"` + Followers_url string `json:"followers_url"` + Name string `json:"name,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Starred_url string `json:"starred_url"` + Avatar_url string `json:"avatar_url"` + Html_url string `json:"html_url"` + Gists_url string `json:"gists_url"` + Starred_at string `json:"starred_at,omitempty"` + Repos_url string `json:"repos_url"` + Site_admin bool `json:"site_admin"` + Received_events_url string `json:"received_events_url"` + Subscriptions_url string `json:"subscriptions_url"` + TypeField string `json:"type"` + Following_url string `json:"following_url"` + Node_id string `json:"node_id"` + Gravatar_id string `json:"gravatar_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Diff_url string `json:"diff_url"` + Html_url string `json:"html_url"` + Merge_base_commit Commit `json:"merge_base_commit"` // Commit + Permalink_url string `json:"permalink_url"` + Status string `json:"status"` + Total_commits int `json:"total_commits"` + Files []GeneratedType `json:"files,omitempty"` + Patch_url string `json:"patch_url"` + Ahead_by int `json:"ahead_by"` + Commits []Commit `json:"commits"` + Url string `json:"url"` + Base_commit Commit `json:"base_commit"` // Commit + Behind_by int `json:"behind_by"` +} + +// Milestone represents the Milestone schema from the OpenAPI specification +type Milestone struct { + Number int `json:"number"` // The number of the milestone. + Closed_issues int `json:"closed_issues"` + Due_on string `json:"due_on"` + Node_id string `json:"node_id"` + Description string `json:"description"` + Html_url string `json:"html_url"` + Open_issues int `json:"open_issues"` + Title string `json:"title"` // The title of the milestone. + Labels_url string `json:"labels_url"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Id int `json:"id"` + State string `json:"state"` // The state of the milestone. + Updated_at string `json:"updated_at"` + Closed_at string `json:"closed_at"` + Creator GeneratedType `json:"creator"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url,omitempty"` + Sha string `json:"sha"` + Tree []map[string]interface{} `json:"tree"` // Objects specifying a tree structure + Truncated bool `json:"truncated"` +} + +// Issue represents the Issue schema from the OpenAPI specification +type Issue struct { + Id int64 `json:"id"` + Closed_by GeneratedType `json:"closed_by,omitempty"` // A GitHub user. + Created_at string `json:"created_at"` + Locked bool `json:"locked"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Timeline_url string `json:"timeline_url,omitempty"` + Events_url string `json:"events_url"` + Url string `json:"url"` // URL for the issue + Labels []interface{} `json:"labels"` // Labels to associate with this issue; pass one or more label names to replace the set of labels on this issue; send an empty array to clear all labels from the issue; note that the labels are silently dropped for users without push access to the repository + Body_html string `json:"body_html,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Node_id string `json:"node_id"` + Body string `json:"body,omitempty"` // Contents of the issue + State_reason string `json:"state_reason,omitempty"` // The reason for the current state + Repository Repository `json:"repository,omitempty"` // A repository on GitHub. + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Draft bool `json:"draft,omitempty"` + Html_url string `json:"html_url"` + User GeneratedType `json:"user"` // A GitHub user. + Comments int `json:"comments"` + Repository_url string `json:"repository_url"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Updated_at string `json:"updated_at"` + Closed_at string `json:"closed_at"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Title string `json:"title"` // Title of the issue + Labels_url string `json:"labels_url"` + Sub_issues_summary GeneratedType `json:"sub_issues_summary,omitempty"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Comments_url string `json:"comments_url"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Number int `json:"number"` // Number uniquely identifying the issue within its repository + State string `json:"state"` // State of the issue; either 'open' or 'closed' + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Body_text string `json:"body_text,omitempty"` + Reactions GeneratedType `json:"reactions,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Review_requester GeneratedType `json:"review_requester,omitempty"` // A GitHub user. + Assigner GeneratedType `json:"assigner,omitempty"` // A GitHub user. + Commit_url string `json:"commit_url"` + Node_id string `json:"node_id"` + Requested_team Team `json:"requested_team,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Created_at string `json:"created_at"` + Project_card GeneratedType `json:"project_card,omitempty"` // Issue Event Project Card + Id int64 `json:"id"` + Url string `json:"url"` + Commit_id string `json:"commit_id"` + Issue GeneratedType `json:"issue,omitempty"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Label GeneratedType `json:"label,omitempty"` // Issue Event Label + Requested_reviewer GeneratedType `json:"requested_reviewer,omitempty"` // A GitHub user. + Actor GeneratedType `json:"actor"` // A GitHub user. + Milestone GeneratedType `json:"milestone,omitempty"` // Issue Event Milestone + Assignee GeneratedType `json:"assignee,omitempty"` // A GitHub user. + Dismissed_review GeneratedType `json:"dismissed_review,omitempty"` + Event string `json:"event"` + Rename GeneratedType `json:"rename,omitempty"` // Issue Event Rename + Author_association string `json:"author_association,omitempty"` // How the author is associated with the repository. + Lock_reason string `json:"lock_reason,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// Enterprise represents the Enterprise schema from the OpenAPI specification +type Enterprise struct { + Avatar_url string `json:"avatar_url"` + Created_at string `json:"created_at"` + Description string `json:"description,omitempty"` // A short description of the enterprise. + Html_url string `json:"html_url"` + Slug string `json:"slug"` // The slug url identifier for the enterprise. + Id int `json:"id"` // Unique identifier of the enterprise + Name string `json:"name"` // The name of the enterprise. + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Website_url string `json:"website_url,omitempty"` // The enterprise's website URL. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Cpu_cores int `json:"cpu_cores"` // The number of cores. + Id string `json:"id"` // The ID used for the `size` parameter when creating a new runner. + Memory_gb int `json:"memory_gb"` // The available RAM for the machine spec. + Storage_gb int `json:"storage_gb"` // The available SSD storage for the machine spec. +} + +// Hook represents the Hook schema from the OpenAPI specification +type Hook struct { + Id int `json:"id"` // Unique identifier of the webhook. + Test_url string `json:"test_url"` + TypeField string `json:"type"` + Ping_url string `json:"ping_url"` + Url string `json:"url"` + Config GeneratedType `json:"config"` // Configuration object of the webhook + Created_at string `json:"created_at"` + Deliveries_url string `json:"deliveries_url,omitempty"` + Events []string `json:"events"` // Determines what events the hook is triggered for. Default: ['push']. + Updated_at string `json:"updated_at"` + Active bool `json:"active"` // Determines whether the hook is actually triggered on pushes. + Last_response GeneratedType `json:"last_response"` + Name string `json:"name"` // The name of a valid service, use 'web' for a webhook. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // A GitHub repository. + Status string `json:"status,omitempty"` // The attachment status of the code security configuration on the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Marketplace_purchase map[string]interface{} `json:"marketplace_purchase"` + Previous_marketplace_purchase Webhookspreviousmarketplacepurchase `json:"previous_marketplace_purchase,omitempty"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Effective_date string `json:"effective_date"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2_status_update GeneratedType `json:"projects_v2_status_update"` // An status update belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_property map[string]interface{} `json:"repository_property"` +} + +// Webhooksmilestone represents the Webhooksmilestone schema from the OpenAPI specification +type Webhooksmilestone struct { + Closed_issues int `json:"closed_issues"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Description string `json:"description"` + Open_issues int `json:"open_issues"` + Title string `json:"title"` // The title of the milestone. + Url string `json:"url"` + Closed_at string `json:"closed_at"` + Creator map[string]interface{} `json:"creator"` + State string `json:"state"` // The state of the milestone. + Due_on string `json:"due_on"` + Labels_url string `json:"labels_url"` + Number int `json:"number"` // The number of the milestone. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Comment Webhooksissuecomment `json:"comment"` // The [comment](https://docs.github.com/rest/issues/comments#get-an-issue-comment) itself. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Sender GeneratedType `json:"sender"` // A GitHub user. + Issue interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) the comment belongs to. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Changes Webhookschanges `json:"changes"` // The changes to the comment. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow Webhooksworkflow `json:"workflow"` + Workflow_run map[string]interface{} `json:"workflow_run"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request_title_url string `json:"pull_request_title_url"` // The API URL to get the pull request where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_name map[string]interface{} `json:"repository_name"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Size int `json:"size"` + Links map[string]interface{} `json:"_links"` + Content string `json:"content"` + Download_url string `json:"download_url"` + Encoding string `json:"encoding"` + Git_url string `json:"git_url"` + Name string `json:"name"` + Target string `json:"target,omitempty"` + Html_url string `json:"html_url"` + Path string `json:"path"` + Sha string `json:"sha"` + Submodule_git_url string `json:"submodule_git_url,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Paused bool `json:"paused"` // Whether Dependabot security updates are paused for the repository. + Enabled bool `json:"enabled"` // Whether Dependabot security updates are enabled for the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + State string `json:"state"` // State of the issue; either 'open' or 'closed' + Performed_via_github_app GeneratedType `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Comments_url string `json:"comments_url"` + Number int `json:"number"` // Number uniquely identifying the issue within its repository + Title string `json:"title"` // Title of the issue + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Created_at string `json:"created_at"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Closed_at string `json:"closed_at"` + Labels_url string `json:"labels_url"` + Comments int `json:"comments"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Repository Repository `json:"repository,omitempty"` // A repository on GitHub. + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Events_url string `json:"events_url"` + Repository_url string `json:"repository_url"` + Body_html string `json:"body_html,omitempty"` + Sub_issues_summary GeneratedType `json:"sub_issues_summary,omitempty"` + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Node_id string `json:"node_id"` + State_reason string `json:"state_reason,omitempty"` // The reason for the current state + User GeneratedType `json:"user"` // A GitHub user. + Timeline_url string `json:"timeline_url,omitempty"` + Html_url string `json:"html_url"` + Reactions GeneratedType `json:"reactions,omitempty"` + Url string `json:"url"` // URL for the issue + Labels []interface{} `json:"labels"` // Labels to associate with this issue; pass one or more label names to replace the set of labels on this issue; send an empty array to clear all labels from the issue; note that the labels are silently dropped for users without push access to the repository + Locked bool `json:"locked"` + Draft bool `json:"draft,omitempty"` + Body_text string `json:"body_text,omitempty"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Updated_at string `json:"updated_at"` + Body string `json:"body,omitempty"` // Contents of the issue + Id int64 `json:"id"` + Closed_by GeneratedType `json:"closed_by,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Assignment string `json:"assignment,omitempty"` // Determines if the user has a direct, indirect, or mixed relationship to a role + Avatar_url string `json:"avatar_url"` + Starred_at string `json:"starred_at,omitempty"` + Events_url string `json:"events_url"` + Id int `json:"id"` + Email string `json:"email,omitempty"` + Followers_url string `json:"followers_url"` + Node_id string `json:"node_id"` + Gravatar_id string `json:"gravatar_id"` + Site_admin bool `json:"site_admin"` + Gists_url string `json:"gists_url"` + Inherited_from []GeneratedType `json:"inherited_from,omitempty"` // Team the user has gotten the role through + Received_events_url string `json:"received_events_url"` + Repos_url string `json:"repos_url"` + Login string `json:"login"` + Following_url string `json:"following_url"` + Subscriptions_url string `json:"subscriptions_url"` + Html_url string `json:"html_url"` + Organizations_url string `json:"organizations_url"` + TypeField string `json:"type"` + Url string `json:"url"` + User_view_type string `json:"user_view_type,omitempty"` + Starred_url string `json:"starred_url"` + Name string `json:"name,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Html_url string `json:"html_url,omitempty"` + Key string `json:"key"` + Name string `json:"name"` + Node_id string `json:"node_id"` + Spdx_id string `json:"spdx_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Github_owned_allowed bool `json:"github_owned_allowed,omitempty"` // Whether GitHub-owned actions are allowed. For example, this includes the actions in the `actions` organization. + Patterns_allowed []string `json:"patterns_allowed,omitempty"` // Specifies a list of string-matching patterns to allow specific action(s) and reusable workflow(s). Wildcards, tags, and SHAs are allowed. For example, `monalisa/octocat@*`, `monalisa/octocat@v2`, `monalisa/*`. > [!NOTE] > The `patterns_allowed` setting only applies to public repositories. + Verified_allowed bool `json:"verified_allowed,omitempty"` // Whether actions from GitHub Marketplace verified creators are allowed. Set to `true` to allow all actions by GitHub Marketplace verified creators. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2_status_update GeneratedType `json:"projects_v2_status_update"` // An status update belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int64 `json:"id"` + Number int `json:"number"` + Url string `json:"url"` + Base map[string]interface{} `json:"base"` + Head map[string]interface{} `json:"head"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ref_name string `json:"ref_name"` + Size int `json:"size"` + Oid string `json:"oid"` + Path string `json:"path"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Can_approve_pull_request_reviews bool `json:"can_approve_pull_request_reviews"` // Whether GitHub Actions can approve pull requests. Enabling this can be a security risk. + Default_workflow_permissions string `json:"default_workflow_permissions"` // The default workflow permissions granted to the GITHUB_TOKEN when running workflows. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Commit_oid string `json:"commit_oid"` // The commit SHA of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Ref string `json:"ref"` // The Git reference of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Alert GeneratedType `json:"alert"` // A Dependabot alert. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type,omitempty"` // The type of scan + Completed_at string `json:"completed_at,omitempty"` // The time that the scan was completed. Empty if the scan is running + Started_at string `json:"started_at,omitempty"` // The time that the scan was started. Empty if the scan is pending + Status string `json:"status,omitempty"` // The state of the scan. Either "completed", "running", or "pending" +} + +// Snapshot represents the Snapshot schema from the OpenAPI specification +type Snapshot struct { + Metadata Metadata `json:"metadata,omitempty"` // User-defined metadata to store domain-specific information limited to 8 keys with scalar values. + Ref string `json:"ref"` // The repository branch that triggered this snapshot. + Scanned string `json:"scanned"` // The time at which the snapshot was scanned. + Sha string `json:"sha"` // The commit SHA associated with this dependency snapshot. Maximum length: 40 characters. + Version int `json:"version"` // The version of the repository snapshot submission. + Detector map[string]interface{} `json:"detector"` // A description of the detector used. + Job map[string]interface{} `json:"job"` + Manifests map[string]interface{} `json:"manifests,omitempty"` // A collection of package manifests, which are a collection of related dependencies declared in a file or representing a logical group of dependencies. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dismissed_comment string `json:"dismissed_comment"` // An optional comment associated with the alert's dismissal. + Dependency map[string]interface{} `json:"dependency"` // Details for the vulnerable dependency. + Number int `json:"number"` // The security alert number. + Auto_dismissed_at string `json:"auto_dismissed_at,omitempty"` // The time that the alert was auto-dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Security_advisory GeneratedType `json:"security_advisory"` // Details for the GitHub Security Advisory. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Security_vulnerability GeneratedType `json:"security_vulnerability"` // Details pertaining to one vulnerable version range for the advisory. + Updated_at string `json:"updated_at"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + State string `json:"state"` // The state of the Dependabot alert. + Url string `json:"url"` // The REST API URL of the alert resource. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Fixed_at string `json:"fixed_at"` // The time that the alert was no longer detected and was considered fixed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Repository GeneratedType `json:"repository"` // A GitHub repository. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_reason string `json:"dismissed_reason"` // The reason that the alert was dismissed. +} + +// Webhooksmilestone3 represents the Webhooksmilestone3 schema from the OpenAPI specification +type Webhooksmilestone3 struct { + Node_id string `json:"node_id"` + Closed_issues int `json:"closed_issues"` + Title string `json:"title"` // The title of the milestone. + Labels_url string `json:"labels_url"` + Id int `json:"id"` + Updated_at string `json:"updated_at"` + Number int `json:"number"` // The number of the milestone. + Open_issues int `json:"open_issues"` + State string `json:"state"` // The state of the milestone. + Description string `json:"description"` + Creator map[string]interface{} `json:"creator"` + Due_on string `json:"due_on"` + Html_url string `json:"html_url"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Closed_at string `json:"closed_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the machine. + Operating_system string `json:"operating_system"` // The operating system of the machine. + Prebuild_availability string `json:"prebuild_availability"` // Whether a prebuild is currently available when creating a codespace for this machine and repository. If a branch was not specified as a ref, the default branch will be assumed. Value will be "null" if prebuilds are not supported or prebuild availability could not be determined. Value will be "none" if no prebuild is available. Latest values "ready" and "in_progress" indicate the prebuild availability status. + Storage_in_bytes int `json:"storage_in_bytes"` // How much storage is available to the codespace. + Cpus int `json:"cpus"` // How many cores are available to the codespace. + Display_name string `json:"display_name"` // The display name of the machine includes cores, memory, and storage. + Memory_in_bytes int `json:"memory_in_bytes"` // How much memory is available to the codespace. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Pull_request map[string]interface{} `json:"pull_request"` + Reason string `json:"reason,omitempty"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender"` // A GitHub user. + Number int `json:"number"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Throttled_at string `json:"throttled_at,omitempty"` // Time when the webhook delivery was throttled. + Guid string `json:"guid"` // Unique identifier for the event (shared with all deliveries for all webhooks that subscribe to this event). + Id int64 `json:"id"` // Unique identifier of the webhook delivery. + Status_code int `json:"status_code"` // Status code received when delivery was made. + Action string `json:"action"` // The type of activity for the event that triggered the delivery. + Delivered_at string `json:"delivered_at"` // Time when the webhook delivery occurred. + Repository_id int64 `json:"repository_id"` // The id of the repository associated with this event. + Status string `json:"status"` // Describes the response returned after attempting the delivery. + Duration float64 `json:"duration"` // Time spent delivering. + Event string `json:"event"` // The event that triggered the delivery. + Installation_id int64 `json:"installation_id"` // The id of the GitHub App installation associated with this event. + Redelivery bool `json:"redelivery"` // Whether the webhook delivery is a redelivery. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request GeneratedType `json:"pull_request"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Run_id int `json:"run_id,omitempty"` // ID of the corresponding run. + Run_url string `json:"run_url,omitempty"` // URL of the corresponding run. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description"` // Description of the team + Id int `json:"id"` // Unique identifier of the team + Slug string `json:"slug"` + Members_url string `json:"members_url"` + Privacy string `json:"privacy,omitempty"` // The level of privacy this team should have + Html_url string `json:"html_url"` + Ldap_dn string `json:"ldap_dn,omitempty"` // Distinguished Name (DN) that team maps to within LDAP environment + Name string `json:"name"` // Name of the team + Node_id string `json:"node_id"` + Repositories_url string `json:"repositories_url"` + Notification_setting string `json:"notification_setting,omitempty"` // The notification setting the team has set + Permission string `json:"permission"` // Permission that the team will have for its repositories + Url string `json:"url"` // URL for the team +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Key string `json:"key"` // The Base64 encoded public key. + Key_id string `json:"key_id"` // The identifier for the key. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Member Webhooksuser `json:"member"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Pull_request map[string]interface{} `json:"pull_request"` + Sender GeneratedType `json:"sender"` // A GitHub user. + After string `json:"after"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Number int `json:"number"` // The pull request number. + Before string `json:"before"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` // A Dependabot alert. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Milestone Milestone `json:"milestone,omitempty"` // A collection of related issues and pull requests. + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request Webhookspullrequest5 `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// Webhookspreviousmarketplacepurchase represents the Webhookspreviousmarketplacepurchase schema from the OpenAPI specification +type Webhookspreviousmarketplacepurchase struct { + Billing_cycle string `json:"billing_cycle"` + Free_trial_ends_on interface{} `json:"free_trial_ends_on"` + Next_billing_date string `json:"next_billing_date,omitempty"` + On_free_trial bool `json:"on_free_trial"` + Plan map[string]interface{} `json:"plan"` + Unit_count int `json:"unit_count"` + Account map[string]interface{} `json:"account"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2 GeneratedType `json:"projects_v2"` // A projects v2 project +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Plan GeneratedType `json:"plan"` // Marketplace Listing Plan + Unit_count int `json:"unit_count"` + Updated_at string `json:"updated_at"` + Account GeneratedType `json:"account"` + Billing_cycle string `json:"billing_cycle"` + Free_trial_ends_on string `json:"free_trial_ends_on"` + Next_billing_date string `json:"next_billing_date"` + On_free_trial bool `json:"on_free_trial"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Permission string `json:"permission"` + User GeneratedType `json:"user"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Path string `json:"path"` + Commit_id string `json:"commit_id"` + Position int `json:"position"` + Reactions GeneratedType `json:"reactions,omitempty"` + Created_at string `json:"created_at"` + Html_url string `json:"html_url"` + Line int `json:"line"` + Updated_at string `json:"updated_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Node_id string `json:"node_id"` + Url string `json:"url"` + User GeneratedType `json:"user"` // A GitHub user. + Body string `json:"body"` + Id int `json:"id"` +} + +// Webhooksteam1 represents the Webhooksteam1 schema from the OpenAPI specification +type Webhooksteam1 struct { + Html_url string `json:"html_url,omitempty"` + Name string `json:"name"` // Name of the team + Parent map[string]interface{} `json:"parent,omitempty"` + Privacy string `json:"privacy,omitempty"` + Description string `json:"description,omitempty"` // Description of the team + Notification_setting string `json:"notification_setting,omitempty"` // Whether team members will receive notifications when their team is @mentioned + Slug string `json:"slug,omitempty"` + Deleted bool `json:"deleted,omitempty"` + Id int `json:"id"` // Unique identifier of the team + Permission string `json:"permission,omitempty"` // Permission that the team will have for its repositories + Repositories_url string `json:"repositories_url,omitempty"` + Members_url string `json:"members_url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Url string `json:"url,omitempty"` // URL for the team +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Blob_url string `json:"blob_url"` // The API URL to get the associated blob resource + End_column float64 `json:"end_column"` // The column at which the secret ends within the end line when the file is interpreted as 8BIT ASCII + Blob_sha string `json:"blob_sha"` // SHA-1 hash ID of the associated blob + Commit_url string `json:"commit_url"` // The API URL to get the associated commit resource + Start_column float64 `json:"start_column"` // The column at which the secret starts within the start line when the file is interpreted as 8BIT ASCII + Start_line float64 `json:"start_line"` // Line number at which the secret starts in the file + Commit_sha string `json:"commit_sha"` // SHA-1 hash ID of the associated commit + End_line float64 `json:"end_line"` // Line number at which the secret ends in the file + Path string `json:"path"` // The file path in the repository +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parent_issue_id float64 `json:"parent_issue_id"` // The ID of the parent issue. + Parent_issue_repo Repository `json:"parent_issue_repo"` // A repository on GitHub. + Sub_issue_id float64 `json:"sub_issue_id"` // The ID of the sub-issue. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Parent_issue Issue `json:"parent_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Action string `json:"action"` + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Sub_issue Issue `json:"sub_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow string `json:"workflow"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Inputs map[string]interface{} `json:"inputs"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Ref string `json:"ref"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation Installation `json:"installation"` // Installation + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repositories []map[string]interface{} `json:"repositories,omitempty"` // An array of repository objects that the installation can access. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Requester interface{} `json:"requester,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + State string `json:"state"` // Whether to approve or reject deployment to the specified environments. + Comment string `json:"comment,omitempty"` // Optional comment to include with the review. + Environment_name string `json:"environment_name"` // The name of the environment to approve or reject. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Comment Webhookscomment `json:"comment"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request GeneratedType `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Uniques int `json:"uniques"` + Views []Traffic `json:"views"` + Count int `json:"count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Alert GeneratedType `json:"alert"` // A Dependabot alert. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Avatar_url string `json:"avatar_url"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Permissions map[string]interface{} `json:"permissions"` // Permissions requested, categorized by type of permission. + Repositories_url string `json:"repositories_url"` // URL to the list of repositories requested to be accessed via fine-grained personal access token. Should only be followed when `repository_selection` is `subset`. + Token_expires_at string `json:"token_expires_at"` // Date and time when the associated fine-grained personal access token expires. + Token_id int `json:"token_id"` // Unique identifier of the user's token. This field can also be found in audit log events and the organization's settings for their PAT grants. + Token_name string `json:"token_name"` // The name given to the user's token. This field can also be found in an organization's settings page for Active Tokens. + Id int `json:"id"` // Unique identifier of the request for access via fine-grained personal access token. The `pat_request_id` used to review PAT requests. + Reason string `json:"reason"` // Reason for requesting access. + Repository_selection string `json:"repository_selection"` // Type of repository selection requested. + Token_expired bool `json:"token_expired"` // Whether the associated fine-grained personal access token has expired. + Token_last_used_at string `json:"token_last_used_at"` // Date and time when the associated fine-grained personal access token was last used for authentication. + Created_at string `json:"created_at"` // Date and time when the request for access was created. + Owner GeneratedType `json:"owner"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Protected bool `json:"protected"` + Protection GeneratedType `json:"protection"` // Branch Protection + Protection_url string `json:"protection_url"` + Required_approving_review_count int `json:"required_approving_review_count,omitempty"` + Links map[string]interface{} `json:"_links"` + Commit Commit `json:"commit"` // Commit + Name string `json:"name"` + Pattern string `json:"pattern,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` +} + +// Hovercard represents the Hovercard schema from the OpenAPI specification +type Hovercard struct { + Contexts []map[string]interface{} `json:"contexts"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Url string `json:"url"` + Yearly_price_in_cents int `json:"yearly_price_in_cents"` + Bullets []string `json:"bullets"` + Has_free_trial bool `json:"has_free_trial"` + Monthly_price_in_cents int `json:"monthly_price_in_cents"` + Name string `json:"name"` + State string `json:"state"` + Price_model string `json:"price_model"` + Description string `json:"description"` + Number int `json:"number"` + Unit_name string `json:"unit_name"` + Accounts_url string `json:"accounts_url"` +} + +// Webhooksanswer represents the Webhooksanswer schema from the OpenAPI specification +type Webhooksanswer struct { + Discussion_id int `json:"discussion_id"` + Repository_url string `json:"repository_url"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Node_id string `json:"node_id"` + Parent_id interface{} `json:"parent_id"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + Updated_at string `json:"updated_at"` + Body string `json:"body"` + Child_comment_count int `json:"child_comment_count"` + Created_at string `json:"created_at"` + Html_url string `json:"html_url"` + User map[string]interface{} `json:"user"` + Id int `json:"id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes Webhooksprojectchanges `json:"changes"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Review Webhooksreview `json:"review"` // The review that was affected. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Commits_url string `json:"commits_url"` + Comments_url string `json:"comments_url"` + Number int `json:"number"` // Number uniquely identifying the pull request within its repository. + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Requested_reviewers []GeneratedType `json:"requested_reviewers,omitempty"` + State string `json:"state"` // State of this Pull Request. Either `open` or `closed`. + User GeneratedType `json:"user"` // A GitHub user. + Merge_commit_sha string `json:"merge_commit_sha"` + Base map[string]interface{} `json:"base"` + Patch_url string `json:"patch_url"` + Merged_by GeneratedType `json:"merged_by"` // A GitHub user. + Statuses_url string `json:"statuses_url"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Review_comment_url string `json:"review_comment_url"` + Auto_merge GeneratedType `json:"auto_merge"` // The status of auto merging a pull request. + Deletions int `json:"deletions"` + Maintainer_can_modify bool `json:"maintainer_can_modify"` // Indicates whether maintainers can modify the pull request. + Head map[string]interface{} `json:"head"` + Locked bool `json:"locked"` + Title string `json:"title"` // The title of the pull request. + Html_url string `json:"html_url"` + Diff_url string `json:"diff_url"` + Review_comments int `json:"review_comments"` + Updated_at string `json:"updated_at"` + Node_id string `json:"node_id"` + Draft bool `json:"draft,omitempty"` // Indicates whether or not the pull request is a draft. + Merged bool `json:"merged"` + Labels []map[string]interface{} `json:"labels"` + Body string `json:"body"` + Changed_files int `json:"changed_files"` + Comments int `json:"comments"` + Mergeable_state string `json:"mergeable_state"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Requested_teams []GeneratedType `json:"requested_teams,omitempty"` + Url string `json:"url"` + Rebaseable bool `json:"rebaseable,omitempty"` + Commits int `json:"commits"` + Merged_at string `json:"merged_at"` + Mergeable bool `json:"mergeable"` + Id int64 `json:"id"` + Issue_url string `json:"issue_url"` + Additions int `json:"additions"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Closed_at string `json:"closed_at"` + Links map[string]interface{} `json:"_links"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Review_comments_url string `json:"review_comments_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged. + Merge_commit_message string `json:"merge_commit_message,omitempty"` // The default value for a merge commit message. - `PR_TITLE` - default to the pull request's title. - `PR_BODY` - default to the pull request's body. - `BLANK` - default to a blank commit message. + Merge_commit_title string `json:"merge_commit_title,omitempty"` // The default value for a merge commit title. - `PR_TITLE` - default to the pull request's title. - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., "Merge pull request #123 from branch-name"). + Squash_merge_commit_message string `json:"squash_merge_commit_message,omitempty"` // The default value for a squash merge commit message: - `PR_BODY` - default to the pull request's body. - `COMMIT_MESSAGES` - default to the branch's commit messages. - `BLANK` - default to a blank commit message. + Squash_merge_commit_title string `json:"squash_merge_commit_title,omitempty"` // The default value for a squash merge commit title: - `PR_TITLE` - default to the pull request's title. - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` // Whether a squash merge commit can use the pull request title as default. **This property is closing down. Please use `squash_merge_commit_title` instead.** + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow auto-merge for pull requests. + Allow_update_branch bool `json:"allow_update_branch,omitempty"` // Whether to allow updating the pull request's branch. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Credits []map[string]interface{} `json:"credits,omitempty"` // A list of users receiving credit for their participation in the security advisory. + Summary string `json:"summary"` // A short summary of the advisory. + Vulnerabilities []map[string]interface{} `json:"vulnerabilities"` // A product affected by the vulnerability detailed in a repository security advisory. + Cvss_vector_string string `json:"cvss_vector_string,omitempty"` // The CVSS vector that calculates the severity of the advisory. You must choose between setting this field or `severity`. + Description string `json:"description"` // A detailed description of what the advisory impacts. + Severity string `json:"severity,omitempty"` // The severity of the advisory. You must choose between setting this field or `cvss_vector_string`. + Cve_id string `json:"cve_id,omitempty"` // The Common Vulnerabilities and Exposures (CVE) ID. + Cwe_ids []string `json:"cwe_ids,omitempty"` // A list of Common Weakness Enumeration (CWE) IDs. + Start_private_fork bool `json:"start_private_fork,omitempty"` // Whether to create a temporary private fork of the repository to collaborate on a fix. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pages []map[string]interface{} `json:"pages"` // The pages that were updated. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2_status_update GeneratedType `json:"projects_v2_status_update"` // An status update belonging to a project + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Warning string `json:"warning"` // Warning generated when processing the analysis + Id int `json:"id"` // Unique identifier for this analysis. + Results_count int `json:"results_count"` // The total number of results in the analysis. + Analysis_key string `json:"analysis_key"` // Identifies the configuration under which the analysis was executed. For example, in GitHub Actions this includes the workflow filename and job name. + Category string `json:"category,omitempty"` // Identifies the configuration under which the analysis was executed. Used to distinguish between multiple analyses for the same tool and commit, but performed on different languages or different parts of the code. + Deletable bool `json:"deletable"` + Sarif_id string `json:"sarif_id"` // An identifier for the upload. + Rules_count int `json:"rules_count"` // The total number of rules used in the analysis. + Ref string `json:"ref"` // The Git reference, formatted as `refs/pull//merge`, `refs/pull//head`, `refs/heads/` or simply ``. + Url string `json:"url"` // The REST API URL of the analysis resource. + Created_at string `json:"created_at"` // The time that the analysis was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Tool GeneratedType `json:"tool"` + Environment string `json:"environment"` // Identifies the variable values associated with the environment in which this analysis was performed. + ErrorField string `json:"error"` + Commit_sha string `json:"commit_sha"` // The SHA of the commit to which the analysis you are uploading relates. +} + +// Root represents the Root schema from the OpenAPI specification +type Root struct { + Current_user_repositories_url string `json:"current_user_repositories_url"` + Authorizations_url string `json:"authorizations_url"` + Current_user_url string `json:"current_user_url"` + User_search_url string `json:"user_search_url"` + Followers_url string `json:"followers_url"` + Notifications_url string `json:"notifications_url"` + Issue_search_url string `json:"issue_search_url"` + User_repositories_url string `json:"user_repositories_url"` + Public_gists_url string `json:"public_gists_url"` + Repository_search_url string `json:"repository_search_url"` + Organization_teams_url string `json:"organization_teams_url"` + Topic_search_url string `json:"topic_search_url,omitempty"` + Hub_url string `json:"hub_url,omitempty"` + User_url string `json:"user_url"` + Feeds_url string `json:"feeds_url"` + Gists_url string `json:"gists_url"` + Issues_url string `json:"issues_url"` + Keys_url string `json:"keys_url"` + User_organizations_url string `json:"user_organizations_url"` + Events_url string `json:"events_url"` + Emojis_url string `json:"emojis_url"` + Organization_repositories_url string `json:"organization_repositories_url"` + Current_user_authorizations_html_url string `json:"current_user_authorizations_html_url"` + Following_url string `json:"following_url"` + Code_search_url string `json:"code_search_url"` + Commit_search_url string `json:"commit_search_url"` + Label_search_url string `json:"label_search_url"` + Starred_gists_url string `json:"starred_gists_url"` + Repository_url string `json:"repository_url"` + Emails_url string `json:"emails_url"` + Starred_url string `json:"starred_url"` + Rate_limit_url string `json:"rate_limit_url"` + Organization_url string `json:"organization_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Body string `json:"body"` + Patch_url string `json:"patch_url"` + Comments_url string `json:"comments_url"` + Review_comment_url string `json:"review_comment_url"` + Url string `json:"url"` + Requested_reviewers []GeneratedType `json:"requested_reviewers,omitempty"` + Locked bool `json:"locked"` + Commits_url string `json:"commits_url"` + Id int64 `json:"id"` + Merged_at string `json:"merged_at"` + Updated_at string `json:"updated_at"` + Links map[string]interface{} `json:"_links"` + Statuses_url string `json:"statuses_url"` + Labels []map[string]interface{} `json:"labels"` + Draft bool `json:"draft,omitempty"` // Indicates whether or not the pull request is a draft. + Closed_at string `json:"closed_at"` + Auto_merge GeneratedType `json:"auto_merge"` // The status of auto merging a pull request. + Merge_commit_sha string `json:"merge_commit_sha"` + Head map[string]interface{} `json:"head"` + Review_comments_url string `json:"review_comments_url"` + Number int `json:"number"` + Title string `json:"title"` + User GeneratedType `json:"user"` // A GitHub user. + Issue_url string `json:"issue_url"` + Base map[string]interface{} `json:"base"` + Created_at string `json:"created_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Assignees []GeneratedType `json:"assignees,omitempty"` + Html_url string `json:"html_url"` + State string `json:"state"` + Requested_teams []Team `json:"requested_teams,omitempty"` + Diff_url string `json:"diff_url"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository map[string]interface{} `json:"repository,omitempty"` // A git repository + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Team Webhooksteam1 `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Runner_type string `json:"runner_type,omitempty"` // Runner type to be used. + State string `json:"state,omitempty"` // The desired state of code scanning default setup. + Threat_model string `json:"threat_model,omitempty"` // Threat model to be used for code scanning analysis. Use `remote` to analyze only network sources and `remote_and_local` to include local sources like filesystem access, command-line arguments, database reads, environment variable and standard input. + Languages []string `json:"languages,omitempty"` // CodeQL languages to be analyzed. + Query_suite string `json:"query_suite,omitempty"` // CodeQL query suite to be used. + Runner_label string `json:"runner_label,omitempty"` // Runner label to be used if the runner type is labeled. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Score float64 `json:"score"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Url string `json:"url"` + Color string `json:"color"` + Name string `json:"name"` + DefaultField bool `json:"default"` + Id int `json:"id"` + Description string `json:"description"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + End_line int `json:"end_line,omitempty"` + Path string `json:"path,omitempty"` + Start_column int `json:"start_column,omitempty"` + Start_line int `json:"start_line,omitempty"` + End_column int `json:"end_column,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Completed_at string `json:"completed_at,omitempty"` // Completion time of the last export operation + Export_url string `json:"export_url,omitempty"` // Url for fetching export details + Html_url string `json:"html_url,omitempty"` // Web url for the exported branch + Id string `json:"id,omitempty"` // Id for the export details + Sha string `json:"sha,omitempty"` // Git commit SHA of the exported branch + State string `json:"state,omitempty"` // State of the latest export + Branch string `json:"branch,omitempty"` // Name of the exported branch +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Merge_group GeneratedType `json:"merge_group"` // A group of pull requests that the merge queue has grouped together to be merged. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Reason string `json:"reason,omitempty"` // Explains why the merge group is being destroyed. The group could have been merged, removed from the queue (dequeued), or invalidated by an earlier queue entry being dequeued (invalidated). + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// Codespace represents the Codespace schema from the OpenAPI specification +type Codespace struct { + Environment_id string `json:"environment_id"` // UUID identifying this codespace's environment. + Web_url string `json:"web_url"` // URL to access this codespace on the web. + Pending_operation_disabled_reason string `json:"pending_operation_disabled_reason,omitempty"` // Text to show user when codespace is disabled by a pending operation + Prebuild bool `json:"prebuild"` // Whether the codespace was created from a prebuild. + Retention_period_minutes int `json:"retention_period_minutes,omitempty"` // Duration in minutes after codespace has gone idle in which it will be deleted. Must be integer minutes between 0 and 43200 (30 days). + Updated_at string `json:"updated_at"` + Start_url string `json:"start_url"` // API URL to start this codespace. + Git_status map[string]interface{} `json:"git_status"` // Details about the codespace's git repository. + Recent_folders []string `json:"recent_folders"` + Machines_url string `json:"machines_url"` // API URL to access available alternate machine types for this codespace. + Stop_url string `json:"stop_url"` // API URL to stop this codespace. + Created_at string `json:"created_at"` + Pulls_url string `json:"pulls_url"` // API URL for the Pull Request associated with this codespace, if any. + Idle_timeout_notice string `json:"idle_timeout_notice,omitempty"` // Text to show user when codespace idle timeout minutes has been overriden by an organization policy + Pending_operation bool `json:"pending_operation,omitempty"` // Whether or not a codespace has a pending async operation. This would mean that the codespace is temporarily unavailable. The only thing that you can do with a codespace in this state is delete it. + Publish_url string `json:"publish_url,omitempty"` // API URL to publish this codespace to a new repository. + Last_known_stop_notice string `json:"last_known_stop_notice,omitempty"` // The text to display to a user when a codespace has been stopped for a potentially actionable reason. + Billable_owner GeneratedType `json:"billable_owner"` // A GitHub user. + Runtime_constraints map[string]interface{} `json:"runtime_constraints,omitempty"` + State string `json:"state"` // State of this codespace. + Name string `json:"name"` // Automatically generated name of this codespace. + Devcontainer_path string `json:"devcontainer_path,omitempty"` // Path to devcontainer.json from repo root used to create Codespace. + Id int64 `json:"id"` + Last_used_at string `json:"last_used_at"` // Last known time this codespace was started. + Repository GeneratedType `json:"repository"` // Minimal Repository + Location string `json:"location"` // The initally assigned location of a new codespace. + Machine GeneratedType `json:"machine"` // A description of the machine powering a codespace. + Display_name string `json:"display_name,omitempty"` // Display name for this codespace. + Owner GeneratedType `json:"owner"` // A GitHub user. + Retention_expires_at string `json:"retention_expires_at,omitempty"` // When a codespace will be auto-deleted based on the "retention_period_minutes" and "last_used_at" + Url string `json:"url"` // API URL for this codespace. + Idle_timeout_minutes int `json:"idle_timeout_minutes"` // The number of minutes of inactivity after which this codespace will be automatically stopped. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Message string `json:"message,omitempty"` // Commit message to be used. + Target_ref string `json:"target_ref,omitempty"` // The Git reference of target branch for the commit. Branch needs to already exist. For more information, see "[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)" in the Git documentation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Html_url string `json:"html_url"` + Last_edited_at string `json:"last_edited_at"` + Node_id string `json:"node_id"` + Author GeneratedType `json:"author"` // A GitHub user. + Created_at string `json:"created_at"` + Reactions GeneratedType `json:"reactions,omitempty"` + Updated_at string `json:"updated_at"` + Body string `json:"body"` // The main text of the comment. + Body_html string `json:"body_html"` + Body_version string `json:"body_version"` // The current version of the body content. If provided, this update operation will be rejected if the given version does not match the latest version on the server. + Discussion_url string `json:"discussion_url"` + Number int `json:"number"` // The unique sequence number of a team discussion comment. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Verification Verification `json:"verification,omitempty"` + Message string `json:"message"` // Message describing the purpose of the tag + Node_id string `json:"node_id"` + Object map[string]interface{} `json:"object"` + Sha string `json:"sha"` + Tag string `json:"tag"` // Name of the tag + Tagger map[string]interface{} `json:"tagger"` + Url string `json:"url"` // URL for the tag +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Issue_comment_url string `json:"issue_comment_url"` // The API URL to get the issue comment where the secret was detected. +} + +// Activity represents the Activity schema from the OpenAPI specification +type Activity struct { + After string `json:"after"` // The SHA of the commit after the activity. + Before string `json:"before"` // The SHA of the commit before the activity. + Id int `json:"id"` + Node_id string `json:"node_id"` + Ref string `json:"ref"` // The full Git reference, formatted as `refs/heads/`. + Timestamp string `json:"timestamp"` // The time when the activity occurred. + Activity_type string `json:"activity_type"` // The type of the activity that was performed. + Actor GeneratedType `json:"actor"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repositories []map[string]interface{} `json:"repositories,omitempty"` // Repositories in which users used Copilot for Pull Requests to generate pull request summaries + Total_engaged_users int `json:"total_engaged_users,omitempty"` // The number of users who used Copilot for Pull Requests on github.com to generate a pull request summary at least once. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Security_advisory Webhookssecurityadvisory `json:"security_advisory"` // The details of the security advisory, including summary, description, and severity. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// Import represents the Import schema from the OpenAPI specification +type Import struct { + Large_files_count int `json:"large_files_count,omitempty"` + Vcs string `json:"vcs"` + Import_percent int `json:"import_percent,omitempty"` + Svn_root string `json:"svn_root,omitempty"` + Url string `json:"url"` + Has_large_files bool `json:"has_large_files,omitempty"` + Status string `json:"status"` + Authors_url string `json:"authors_url"` + Error_message string `json:"error_message,omitempty"` + Failed_step string `json:"failed_step,omitempty"` + Commit_count int `json:"commit_count,omitempty"` + Use_lfs bool `json:"use_lfs,omitempty"` + Authors_count int `json:"authors_count,omitempty"` + Repository_url string `json:"repository_url"` + Status_text string `json:"status_text,omitempty"` + Tfvc_project string `json:"tfvc_project,omitempty"` + Html_url string `json:"html_url"` + Vcs_url string `json:"vcs_url"` // The URL of the originating repository. + Message string `json:"message,omitempty"` + Project_choices []map[string]interface{} `json:"project_choices,omitempty"` + Large_files_size int `json:"large_files_size,omitempty"` + Svc_root string `json:"svc_root,omitempty"` + Push_percent int `json:"push_percent,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Result_count int `json:"result_count,omitempty"` // The number of results in the case of a successful analysis. This is only available for successful analyses. + Source_location_prefix string `json:"source_location_prefix,omitempty"` // The source location prefix to use. This is only available for successful analyses. + Analysis_status string `json:"analysis_status"` // The new status of the CodeQL variant analysis repository task. + Artifact_size_in_bytes int `json:"artifact_size_in_bytes,omitempty"` // The size of the artifact. This is only available for successful analyses. + Artifact_url string `json:"artifact_url,omitempty"` // The URL of the artifact. This is only available for successful analyses. + Database_commit_sha string `json:"database_commit_sha,omitempty"` // The SHA of the commit the CodeQL database was built against. This is only available for successful analyses. + Failure_message string `json:"failure_message,omitempty"` // The reason of the failure of this repo task. This is only available if the repository task has failed. + Repository GeneratedType `json:"repository"` // A GitHub repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project Webhooksproject `json:"project"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes"` // The changes to the milestone if the action was `edited`. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Milestone Webhooksmilestone `json:"milestone"` // A collection of related issues and pull requests. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Username string `json:"username,omitempty"` // The username to use when authenticating with the private registry. + Visibility string `json:"visibility"` // Which type of organization repositories have access to the private registry. `selected` means only the repositories specified by `selected_repository_ids` can access the private registry. + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the private registry configuration. + Registry_type string `json:"registry_type"` // The registry type. + Selected_repository_ids []int `json:"selected_repository_ids,omitempty"` // An array of repository IDs that can access the organization private registry when `visibility` is set to `selected`. + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Expiry string `json:"expiry,omitempty"` // The duration of the interaction restriction. Default: `one_day`. + Limit string `json:"limit"` // The type of GitHub user that can comment, open issues, or create pull requests while the interaction limit is in effect. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Verification map[string]interface{} `json:"verification"` + Sha string `json:"sha"` // SHA for the commit + Url string `json:"url"` + Message string `json:"message"` // Message describing the purpose of the commit + Parents []map[string]interface{} `json:"parents"` + Committer map[string]interface{} `json:"committer"` // Identifying information for the git-user + Html_url string `json:"html_url"` + Tree map[string]interface{} `json:"tree"` + Author map[string]interface{} `json:"author"` // Identifying information for the git-user +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description"` + Hooks_url string `json:"hooks_url"` + Id int `json:"id"` + Avatar_url string `json:"avatar_url"` + Members_url string `json:"members_url"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Login string `json:"login"` + Events_url string `json:"events_url"` + Issues_url string `json:"issues_url"` + Public_members_url string `json:"public_members_url"` + Repos_url string `json:"repos_url"` +} + +// Webhooksteam represents the Webhooksteam schema from the OpenAPI specification +type Webhooksteam struct { + Members_url string `json:"members_url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Parent map[string]interface{} `json:"parent,omitempty"` + Privacy string `json:"privacy,omitempty"` + Notification_setting string `json:"notification_setting,omitempty"` + Repositories_url string `json:"repositories_url,omitempty"` + Url string `json:"url,omitempty"` // URL for the team + Id int `json:"id"` // Unique identifier of the team + Permission string `json:"permission,omitempty"` // Permission that the team will have for its repositories + Html_url string `json:"html_url,omitempty"` + Name string `json:"name"` // Name of the team + Slug string `json:"slug,omitempty"` + Deleted bool `json:"deleted,omitempty"` + Description string `json:"description,omitempty"` // Description of the team +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enabled bool `json:"enabled,omitempty"` // Whether public IP is enabled. + Length int `json:"length,omitempty"` // The length of the IP prefix. + Prefix string `json:"prefix,omitempty"` // The prefix for the public IP. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Ref string `json:"ref"` // The Git reference of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Commit_oid string `json:"commit_oid"` // The commit SHA of the code scanning alert. When the action is `reopened_by_user` or `closed_by_user`, the event was triggered by the `sender` and this value will be empty. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request_comment_url string `json:"pull_request_comment_url"` // The API URL to get the pull request comment where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Referrer string `json:"referrer"` + Uniques int `json:"uniques"` + Count int `json:"count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commits_url string `json:"commits_url,omitempty"` + Git_push_url string `json:"git_push_url,omitempty"` + Git_pull_url string `json:"git_pull_url,omitempty"` + Url string `json:"url,omitempty"` + User string `json:"user,omitempty"` + Forks_url string `json:"forks_url,omitempty"` + Comments_enabled bool `json:"comments_enabled,omitempty"` + Comments_url string `json:"comments_url,omitempty"` + Created_at string `json:"created_at,omitempty"` + Files map[string]interface{} `json:"files,omitempty"` + Truncated bool `json:"truncated,omitempty"` + Fork_of map[string]interface{} `json:"fork_of,omitempty"` // Gist + Id string `json:"id,omitempty"` + Node_id string `json:"node_id,omitempty"` + Comments int `json:"comments,omitempty"` + Description string `json:"description,omitempty"` + Forks []map[string]interface{} `json:"forks,omitempty"` + Public bool `json:"public,omitempty"` + Html_url string `json:"html_url,omitempty"` + Owner GeneratedType `json:"owner,omitempty"` // A GitHub user. + History []GeneratedType `json:"history,omitempty"` + Updated_at string `json:"updated_at,omitempty"` +} + +// Thread represents the Thread schema from the OpenAPI specification +type Thread struct { + Reason string `json:"reason"` + Subject map[string]interface{} `json:"subject"` + Updated_at string `json:"updated_at"` + Subscription_url string `json:"subscription_url"` + Unread bool `json:"unread"` + Id string `json:"id"` + Last_read_at string `json:"last_read_at"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + From string `json:"from"` + To string `json:"to"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dismissal_approved_by GeneratedType `json:"dismissal_approved_by,omitempty"` // A GitHub user. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_comment string `json:"dismissed_comment,omitempty"` // The dismissal comment associated with the dismissal of the alert. + Url string `json:"url"` // The REST API URL of the alert resource. + Most_recent_instance GeneratedType `json:"most_recent_instance"` + Number int `json:"number"` // The security alert number. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_reason string `json:"dismissed_reason"` // **Required when the state is dismissed.** The reason for dismissing or closing the alert. + Instances_url string `json:"instances_url"` // The REST API URL for fetching the list of instances for an alert. + Fixed_at string `json:"fixed_at,omitempty"` // The time that the alert was no longer detected and was considered fixed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + State string `json:"state"` // State of a code scanning alert. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Rule GeneratedType `json:"rule"` + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Tool GeneratedType `json:"tool"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parent_issue_repo Repository `json:"parent_issue_repo"` // A repository on GitHub. + Sub_issue_id float64 `json:"sub_issue_id"` // The ID of the sub-issue. + Action string `json:"action"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Parent_issue Issue `json:"parent_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Sub_issue Issue `json:"sub_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Parent_issue_id float64 `json:"parent_issue_id"` // The ID of the parent issue. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url,omitempty"` + Created_at string `json:"created_at,omitempty"` + Id int `json:"id,omitempty"` + Key string `json:"key"` // The Base64 encoded public key. + Key_id string `json:"key_id"` // The identifier for the key. + Title string `json:"title,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ldap_dn string `json:"ldap_dn,omitempty"` // Distinguished Name (DN) that team maps to within LDAP environment + Slug string `json:"slug"` + Name string `json:"name"` // Name of the team + Description string `json:"description"` + Id int `json:"id"` // Unique identifier of the team + Permission string `json:"permission"` // Permission that the team will have for its repositories + Created_at string `json:"created_at"` + Members_url string `json:"members_url"` + Node_id string `json:"node_id"` + Parent GeneratedType `json:"parent,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Updated_at string `json:"updated_at"` + Members_count int `json:"members_count"` + Html_url string `json:"html_url"` + Organization GeneratedType `json:"organization"` // Team Organization + Privacy string `json:"privacy,omitempty"` // The level of privacy this team should have + Notification_setting string `json:"notification_setting,omitempty"` // The notification setting the team has set + Repos_count int `json:"repos_count"` + Url string `json:"url"` // URL for the team + Repositories_url string `json:"repositories_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Key string `json:"key"` + Name string `json:"name"` + Node_id string `json:"node_id"` + Spdx_id string `json:"spdx_id"` + Url string `json:"url"` + Html_url string `json:"html_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow Webhooksworkflow `json:"workflow"` + Workflow_run map[string]interface{} `json:"workflow_run"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + State string `json:"state"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Commit_id string `json:"commit_id"` // A commit SHA for the review. + Html_url string `json:"html_url"` + Id int `json:"id"` // Unique identifier of the review + Node_id string `json:"node_id"` + Body string `json:"body"` // The text of the review. + Body_html string `json:"body_html,omitempty"` + Pull_request_url string `json:"pull_request_url"` + Submitted_at string `json:"submitted_at,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. + Links map[string]interface{} `json:"_links"` + Body_text string `json:"body_text,omitempty"` + Event string `json:"event"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Accessible_repositories []GeneratedType `json:"accessible_repositories,omitempty"` + Default_level string `json:"default_level,omitempty"` // The default repository access level for Dependabot updates. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Rule Webhooksrule `json:"rule"` // The branch protection rule. Includes a `name` and all the [branch protection settings](https://docs.github.com/github/administering-a-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#about-branch-protection-settings) applied to branches that match the name. Binary settings are boolean. Multi-level configurations are one of `off`, `non_admins`, or `everyone`. Actor and build lists are arrays of strings. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Date string `json:"date,omitempty"` + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Merge_group GeneratedType `json:"merge_group"` // A group of pull requests that the merge queue has grouped together to be merged. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + State string `json:"state"` // State of the release asset. + Browser_download_url string `json:"browser_download_url"` + Label string `json:"label"` + Name string `json:"name"` // The file name of the asset. + Uploader GeneratedType `json:"uploader"` // A GitHub user. + Content_type string `json:"content_type"` + Digest string `json:"digest"` + Download_count int `json:"download_count"` + Id int `json:"id"` + Size int `json:"size"` + Url string `json:"url"` + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` +} + +// Classroom represents the Classroom schema from the OpenAPI specification +type Classroom struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. + Url string `json:"url"` // The URL of the classroom on GitHub Classroom. + Archived bool `json:"archived"` // Whether classroom is archived. + Id int `json:"id"` // Unique identifier of the classroom. + Name string `json:"name"` // The name of the classroom. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Release Webhooksrelease `json:"release"` // The [release](https://docs.github.com/rest/releases/releases/#get-a-release) object. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Members_can_create_public_repositories bool `json:"members_can_create_public_repositories,omitempty"` + Total_private_repos int `json:"total_private_repos,omitempty"` + Public_members_url string `json:"public_members_url"` + Has_organization_projects bool `json:"has_organization_projects"` + Company string `json:"company,omitempty"` + Members_can_create_pages bool `json:"members_can_create_pages,omitempty"` + Description string `json:"description"` + Private_gists int `json:"private_gists,omitempty"` + Default_repository_permission string `json:"default_repository_permission,omitempty"` + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` + Url string `json:"url"` + Updated_at string `json:"updated_at"` + Members_allowed_repository_creation_type string `json:"members_allowed_repository_creation_type,omitempty"` + Node_id string `json:"node_id"` + Billing_email string `json:"billing_email,omitempty"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Repos_url string `json:"repos_url"` + Following int `json:"following"` + Archived_at string `json:"archived_at"` + Hooks_url string `json:"hooks_url"` + Events_url string `json:"events_url"` + Public_repos int `json:"public_repos"` + Members_can_create_public_pages bool `json:"members_can_create_public_pages,omitempty"` + Id int `json:"id"` + Has_repository_projects bool `json:"has_repository_projects"` + Issues_url string `json:"issues_url"` + Followers int `json:"followers"` + Is_verified bool `json:"is_verified,omitempty"` + Owned_private_repos int `json:"owned_private_repos,omitempty"` + Disk_usage int `json:"disk_usage,omitempty"` + Login string `json:"login"` + Members_can_create_internal_repositories bool `json:"members_can_create_internal_repositories,omitempty"` + TypeField string `json:"type"` + Public_gists int `json:"public_gists"` + Two_factor_requirement_enabled bool `json:"two_factor_requirement_enabled,omitempty"` + Plan map[string]interface{} `json:"plan,omitempty"` + Members_can_create_private_pages bool `json:"members_can_create_private_pages,omitempty"` + Blog string `json:"blog,omitempty"` + Html_url string `json:"html_url"` + Members_can_create_repositories bool `json:"members_can_create_repositories,omitempty"` + Members_can_fork_private_repositories bool `json:"members_can_fork_private_repositories,omitempty"` + Collaborators int `json:"collaborators,omitempty"` + Created_at string `json:"created_at"` + Avatar_url string `json:"avatar_url"` + Twitter_username string `json:"twitter_username,omitempty"` + Members_url string `json:"members_url"` + Location string `json:"location,omitempty"` + Members_can_create_private_repositories bool `json:"members_can_create_private_repositories,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Label Webhookslabel `json:"label,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Can_sign bool `json:"can_sign"` + Emails []map[string]interface{} `json:"emails"` + Can_encrypt_comms bool `json:"can_encrypt_comms"` + Primary_key_id int `json:"primary_key_id"` + Public_key string `json:"public_key"` + Revoked bool `json:"revoked"` + Can_encrypt_storage bool `json:"can_encrypt_storage"` + Subkeys []map[string]interface{} `json:"subkeys"` + Id int64 `json:"id"` + Key_id string `json:"key_id"` + Expires_at string `json:"expires_at"` + Can_certify bool `json:"can_certify"` + Raw_key string `json:"raw_key"` + Created_at string `json:"created_at"` + Name string `json:"name,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` // The date and time at which the secret was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Visibility string `json:"visibility"` // The type of repositories in the organization that the secret is visible to + Created_at string `json:"created_at"` // The date and time at which the secret was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Name string `json:"name"` // The name of the secret + Selected_repositories_url string `json:"selected_repositories_url,omitempty"` // The API URL at which the list of repositories this secret is visible to can be retrieved +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Alert GeneratedType `json:"alert"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + PackageField map[string]interface{} `json:"package"` // Information about the package. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// Webhooksalert represents the Webhooksalert schema from the OpenAPI specification +type Webhooksalert struct { + Severity string `json:"severity"` + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` + Dismissed_at string `json:"dismissed_at,omitempty"` + Affected_package_name string `json:"affected_package_name"` + Dismisser map[string]interface{} `json:"dismisser,omitempty"` + Affected_range string `json:"affected_range"` + External_identifier string `json:"external_identifier"` + Fix_reason string `json:"fix_reason,omitempty"` + Fixed_at string `json:"fixed_at,omitempty"` + Ghsa_id string `json:"ghsa_id"` + Dismiss_reason string `json:"dismiss_reason,omitempty"` + Id int `json:"id"` + State string `json:"state"` + External_reference string `json:"external_reference"` + Fixed_in string `json:"fixed_in,omitempty"` + Number int `json:"number"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Project_id string `json:"project_id,omitempty"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Archived bool `json:"archived,omitempty"` // Whether or not the card is archived + Column_name string `json:"column_name,omitempty"` + Content_url string `json:"content_url,omitempty"` + Id int64 `json:"id"` // The project card's ID + Node_id string `json:"node_id"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Project_url string `json:"project_url"` + Column_url string `json:"column_url"` + Note string `json:"note"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Insecure_ssl GeneratedType `json:"insecure_ssl,omitempty"` + Secret string `json:"secret,omitempty"` // If provided, the `secret` will be used as the `key` to generate the HMAC hex digest value for [delivery signature headers](https://docs.github.com/webhooks/event-payloads/#delivery-headers). + Url string `json:"url,omitempty"` // The URL to which the payloads will be delivered. + Content_type string `json:"content_type,omitempty"` // The media type used to serialize the payloads. Supported values include `json` and `form`. The default is `form`. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Requested_action map[string]interface{} `json:"requested_action,omitempty"` // The action requested by the user. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Check_run GeneratedType `json:"check_run"` // A check performed on the code of a given code change + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request map[string]interface{} `json:"pull_request"` + Label Webhookslabel `json:"label,omitempty"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Number int `json:"number"` // The pull request number. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Branch string `json:"branch"` + Path string `json:"path"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Oid string `json:"oid"` // Full or abbreviated commit hash to reject + Reason string `json:"reason,omitempty"` // Reason for restriction +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Deployments_url string `json:"deployments_url"` + Forks_count int `json:"forks_count"` + Updated_at string `json:"updated_at"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Open_issues int `json:"open_issues"` + Stargazers_url string `json:"stargazers_url"` + Git_commits_url string `json:"git_commits_url"` + Downloads_url string `json:"downloads_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Id int `json:"id"` + Git_url string `json:"git_url"` + Forks int `json:"forks"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Archived bool `json:"archived"` + Collaborators_url string `json:"collaborators_url"` + Ssh_url string `json:"ssh_url"` + Mirror_url string `json:"mirror_url"` + Clone_url string `json:"clone_url"` + Pushed_at string `json:"pushed_at"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Keys_url string `json:"keys_url"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` + Has_projects bool `json:"has_projects"` + Teams_url string `json:"teams_url"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` + Notifications_url string `json:"notifications_url"` + Releases_url string `json:"releases_url"` + Issue_events_url string `json:"issue_events_url"` + Allow_forking bool `json:"allow_forking,omitempty"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Subscription_url string `json:"subscription_url"` + Full_name string `json:"full_name"` + Stargazers_count int `json:"stargazers_count"` + Fork bool `json:"fork"` + Hooks_url string `json:"hooks_url"` + Size int `json:"size"` + Html_url string `json:"html_url"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Contributors_url string `json:"contributors_url"` + Forks_url string `json:"forks_url"` + Commits_url string `json:"commits_url"` + Is_template bool `json:"is_template,omitempty"` + Git_refs_url string `json:"git_refs_url"` + Archive_url string `json:"archive_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Watchers int `json:"watchers"` + Topics []string `json:"topics,omitempty"` + Tags_url string `json:"tags_url"` + Has_wiki bool `json:"has_wiki"` + Labels_url string `json:"labels_url"` + Branches_url string `json:"branches_url"` + Git_tags_url string `json:"git_tags_url"` + Issues_url string `json:"issues_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` + Homepage string `json:"homepage"` + Merges_url string `json:"merges_url"` + Subscribers_url string `json:"subscribers_url"` + Private bool `json:"private"` + Contents_url string `json:"contents_url"` + License GeneratedType `json:"license"` // License Simple + Default_branch string `json:"default_branch"` + Blobs_url string `json:"blobs_url"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Watchers_count int `json:"watchers_count"` + Has_downloads bool `json:"has_downloads"` + Issue_comment_url string `json:"issue_comment_url"` + Name string `json:"name"` + Created_at string `json:"created_at"` + Has_issues bool `json:"has_issues"` + Master_branch string `json:"master_branch,omitempty"` + Events_url string `json:"events_url"` + Has_pages bool `json:"has_pages"` + Comments_url string `json:"comments_url"` + Statuses_url string `json:"statuses_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` + Assignees_url string `json:"assignees_url"` + Svn_url string `json:"svn_url"` + Has_discussions bool `json:"has_discussions,omitempty"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Score float64 `json:"score"` + Compare_url string `json:"compare_url"` + Milestones_url string `json:"milestones_url"` + Open_issues_count int `json:"open_issues_count"` + Trees_url string `json:"trees_url"` + Pulls_url string `json:"pulls_url"` + Languages_url string `json:"languages_url"` + Description string `json:"description"` + Language string `json:"language"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + User GeneratedType `json:"user"` // A GitHub user. + Forks_url string `json:"forks_url"` + History []interface{} `json:"history,omitempty"` + Comments_enabled bool `json:"comments_enabled,omitempty"` + Id string `json:"id"` + Git_push_url string `json:"git_push_url"` + Url string `json:"url"` + Git_pull_url string `json:"git_pull_url"` + Node_id string `json:"node_id"` + Truncated bool `json:"truncated,omitempty"` + Forks []interface{} `json:"forks,omitempty"` + Comments_url string `json:"comments_url"` + Public bool `json:"public"` + Comments int `json:"comments"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Files map[string]interface{} `json:"files"` + Html_url string `json:"html_url"` + Description string `json:"description"` + Commits_url string `json:"commits_url"` + Owner GeneratedType `json:"owner,omitempty"` // A GitHub user. +} + +// Runner represents the Runner schema from the OpenAPI specification +type Runner struct { + Runner_group_id int `json:"runner_group_id,omitempty"` // The ID of the runner group. + Status string `json:"status"` // The status of the runner. + Busy bool `json:"busy"` + Ephemeral bool `json:"ephemeral,omitempty"` + Id int `json:"id"` // The ID of the runner. + Labels []GeneratedType `json:"labels"` + Name string `json:"name"` // The name of the runner. + Os string `json:"os"` // The Operating System of the runner. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Payload string `json:"payload"` // A URL-encoded string of the ping JSON payload. The decoded payload is a JSON object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_name string `json:"repository_name"` + Properties []GeneratedType `json:"properties"` // List of custom property names and associated values + Repository_full_name string `json:"repository_full_name"` + Repository_id int `json:"repository_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Size int `json:"size"` + Url string `json:"url"` + Links map[string]interface{} `json:"_links"` + Path string `json:"path"` + TypeField string `json:"type"` + Download_url string `json:"download_url"` + Git_url string `json:"git_url"` + Html_url string `json:"html_url"` + License GeneratedType `json:"license"` // License Simple + Name string `json:"name"` + Content string `json:"content"` + Encoding string `json:"encoding"` + Sha string `json:"sha"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Commit_id string `json:"commit_id"` + Event string `json:"event"` + Node_id string `json:"node_id"` + Requested_reviewer GeneratedType `json:"requested_reviewer,omitempty"` // A GitHub user. + Requested_team Team `json:"requested_team,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Review_requester GeneratedType `json:"review_requester"` // A GitHub user. + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Id int `json:"id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_request GeneratedType `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Discussion_title_url string `json:"discussion_title_url"` // The URL to the discussion where the secret was detected. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_id int `json:"repository_id"` // The ID of the repository where the workflow is defined + Sha string `json:"sha,omitempty"` // The commit SHA of the workflow file to use + Path string `json:"path"` // The path to the workflow file + Ref string `json:"ref,omitempty"` // The ref (branch or tag) of the workflow file to use +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Definition GeneratedType `json:"definition"` // Custom property defined on an organization +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Project_column Webhooksprojectcolumn `json:"project_column"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Provider string `json:"provider"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Copilot_ide_chat GeneratedType `json:"copilot_ide_chat,omitempty"` // Usage metrics for Copilot Chat in the IDE. + Copilot_ide_code_completions GeneratedType `json:"copilot_ide_code_completions,omitempty"` // Usage metrics for Copilot editor code completions in the IDE. + Date string `json:"date"` // The date for which the usage metrics are aggregated, in `YYYY-MM-DD` format. + Total_active_users int `json:"total_active_users,omitempty"` // The total number of Copilot users with activity belonging to any Copilot feature, globally, for the given day. Includes passive activity such as receiving a code suggestion, as well as engagement activity such as accepting a code suggestion or prompting chat. Does not include authentication events. Is not limited to the individual features detailed on the endpoint. + Total_engaged_users int `json:"total_engaged_users,omitempty"` // The total number of Copilot users who engaged with any Copilot feature, for the given day. Examples include but are not limited to accepting a code suggestion, prompting Copilot chat, or triggering a PR Summary. Does not include authentication events. Is not limited to the individual features detailed on the endpoint. + Copilot_dotcom_chat GeneratedType `json:"copilot_dotcom_chat,omitempty"` // Usage metrics for Copilot Chat in GitHub.com + Copilot_dotcom_pull_requests GeneratedType `json:"copilot_dotcom_pull_requests,omitempty"` // Usage metrics for Copilot for pull requests. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Deployments_url string `json:"deployments_url"` + Git_url string `json:"git_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` + Comments_url string `json:"comments_url"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Html_url string `json:"html_url"` + License GeneratedType `json:"license"` // License Simple + Custom_properties map[string]interface{} `json:"custom_properties,omitempty"` // The custom properties that were defined for the repository. The keys are the custom property names, and the values are the corresponding custom property values. + Pushed_at string `json:"pushed_at"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Has_pages bool `json:"has_pages"` + Pulls_url string `json:"pulls_url"` + Source Repository `json:"source,omitempty"` // A repository on GitHub. + Merge_commit_message string `json:"merge_commit_message,omitempty"` // The default value for a merge commit message. - `PR_TITLE` - default to the pull request's title. - `PR_BODY` - default to the pull request's body. - `BLANK` - default to a blank commit message. + Open_issues int `json:"open_issues"` + Blobs_url string `json:"blobs_url"` + Open_issues_count int `json:"open_issues_count"` + Allow_forking bool `json:"allow_forking,omitempty"` + Parent Repository `json:"parent,omitempty"` // A repository on GitHub. + Updated_at string `json:"updated_at"` + Ssh_url string `json:"ssh_url"` + Events_url string `json:"events_url"` + Branches_url string `json:"branches_url"` + Languages_url string `json:"languages_url"` + Is_template bool `json:"is_template,omitempty"` + Clone_url string `json:"clone_url"` + Squash_merge_commit_message string `json:"squash_merge_commit_message,omitempty"` // The default value for a squash merge commit message: - `PR_BODY` - default to the pull request's body. - `COMMIT_MESSAGES` - default to the branch's commit messages. - `BLANK` - default to a blank commit message. + Archived bool `json:"archived"` + Language string `json:"language"` + Assignees_url string `json:"assignees_url"` + Squash_merge_commit_title string `json:"squash_merge_commit_title,omitempty"` // The default value for a squash merge commit title: - `PR_TITLE` - default to the pull request's title. - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + Organization GeneratedType `json:"organization,omitempty"` // A GitHub user. + Subscribers_count int `json:"subscribers_count"` + Created_at string `json:"created_at"` + Trees_url string `json:"trees_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Network_count int `json:"network_count"` + Topics []string `json:"topics,omitempty"` + Code_of_conduct GeneratedType `json:"code_of_conduct,omitempty"` // Code of Conduct Simple + Subscription_url string `json:"subscription_url"` + Watchers int `json:"watchers"` + Template_repository GeneratedType `json:"template_repository,omitempty"` // A repository on GitHub. + Mirror_url string `json:"mirror_url"` + Releases_url string `json:"releases_url"` + Default_branch string `json:"default_branch"` + Milestones_url string `json:"milestones_url"` + Full_name string `json:"full_name"` + Keys_url string `json:"keys_url"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` + Notifications_url string `json:"notifications_url"` + Stargazers_url string `json:"stargazers_url"` + Teams_url string `json:"teams_url"` + Watchers_count int `json:"watchers_count"` + Downloads_url string `json:"downloads_url"` + Merges_url string `json:"merges_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Forks int `json:"forks"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Fork bool `json:"fork"` + Homepage string `json:"homepage"` + Description string `json:"description"` + Has_issues bool `json:"has_issues"` + Git_tags_url string `json:"git_tags_url"` + Url string `json:"url"` + Collaborators_url string `json:"collaborators_url"` + Compare_url string `json:"compare_url"` + Has_discussions bool `json:"has_discussions"` + Git_refs_url string `json:"git_refs_url"` + Forks_url string `json:"forks_url"` + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is allowed. + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` + Master_branch string `json:"master_branch,omitempty"` + Contents_url string `json:"contents_url"` + Tags_url string `json:"tags_url"` + Id int64 `json:"id"` + Hooks_url string `json:"hooks_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` + Has_projects bool `json:"has_projects"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Svn_url string `json:"svn_url"` + Allow_update_branch bool `json:"allow_update_branch,omitempty"` + Issue_comment_url string `json:"issue_comment_url"` + Security_and_analysis GeneratedType `json:"security_and_analysis,omitempty"` + Private bool `json:"private"` + Stargazers_count int `json:"stargazers_count"` + Commits_url string `json:"commits_url"` + Git_commits_url string `json:"git_commits_url"` + Node_id string `json:"node_id"` + Archive_url string `json:"archive_url"` + Labels_url string `json:"labels_url"` + Issue_events_url string `json:"issue_events_url"` + Subscribers_url string `json:"subscribers_url"` + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` + Issues_url string `json:"issues_url"` + Name string `json:"name"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Has_downloads bool `json:"has_downloads,omitempty"` + Contributors_url string `json:"contributors_url"` + Forks_count int `json:"forks_count"` + Merge_commit_title string `json:"merge_commit_title,omitempty"` // The default value for a merge commit title. - `PR_TITLE` - default to the pull request's title. - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name). + Size int `json:"size"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Statuses_url string `json:"statuses_url"` + Has_wiki bool `json:"has_wiki"` +} + +// Job represents the Job schema from the OpenAPI specification +type Job struct { + Html_url string `json:"html_url"` + Status string `json:"status"` // The phase of the lifecycle that the job is currently in. + Created_at string `json:"created_at"` // The time that the job created, in ISO 8601 format. + Conclusion string `json:"conclusion"` // The outcome of the job. + Run_id int `json:"run_id"` // The id of the associated workflow run. + Head_sha string `json:"head_sha"` // The SHA of the commit that is being run. + Started_at string `json:"started_at"` // The time that the job started, in ISO 8601 format. + Labels []string `json:"labels"` // Labels for the workflow job. Specified by the "runs_on" attribute in the action's workflow file. + Url string `json:"url"` + Run_url string `json:"run_url"` + Runner_id int `json:"runner_id"` // The ID of the runner to which this job has been assigned. (If a runner hasn't yet been assigned, this will be null.) + Steps []map[string]interface{} `json:"steps,omitempty"` // Steps in this job. + Check_run_url string `json:"check_run_url"` + Head_branch string `json:"head_branch"` // The name of the current branch. + Runner_group_name string `json:"runner_group_name"` // The name of the runner group to which this job has been assigned. (If a runner hasn't yet been assigned, this will be null.) + Name string `json:"name"` // The name of the job. + Runner_group_id int `json:"runner_group_id"` // The ID of the runner group to which this job has been assigned. (If a runner hasn't yet been assigned, this will be null.) + Id int `json:"id"` // The id of the job. + Completed_at string `json:"completed_at"` // The time that the job finished, in ISO 8601 format. + Run_attempt int `json:"run_attempt,omitempty"` // Attempt number of the associated workflow run, 1 for first attempt and higher if the workflow was re-run. + Node_id string `json:"node_id"` + Runner_name string `json:"runner_name"` // The name of the runner to which this job has been assigned. (If a runner hasn't yet been assigned, this will be null.) + Workflow_name string `json:"workflow_name"` // The name of the workflow. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Public_ips map[string]interface{} `json:"public_ips"` // Provides details of static public IP limits for GitHub-hosted Hosted Runners +} + +// Topic represents the Topic schema from the OpenAPI specification +type Topic struct { + Names []string `json:"names"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + PackageField map[string]interface{} `json:"package"` // Information about the package. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request map[string]interface{} `json:"pull_request"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Thread map[string]interface{} `json:"thread"` + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + In_reply_to_id int `json:"in_reply_to_id,omitempty"` // The comment ID to reply to. + Url string `json:"url"` // URL for the pull request review comment + Side string `json:"side,omitempty"` // The side of the diff to which the comment applies. The side of the last line of the range for a multi-line comment + Author_association string `json:"author_association"` // How the author is associated with the repository. + Original_line int `json:"original_line,omitempty"` // The line of the blob to which the comment applies. The last line of the range for a multi-line comment + Position int `json:"position,omitempty"` // The line index in the diff to which the comment applies. This field is closing down; use `line` instead. + Reactions GeneratedType `json:"reactions,omitempty"` + Pull_request_review_id int64 `json:"pull_request_review_id"` // The ID of the pull request review to which the comment belongs. + Subject_type string `json:"subject_type,omitempty"` // The level at which the comment is targeted, can be a diff line or a file. + Body_html string `json:"body_html,omitempty"` + Original_start_line int `json:"original_start_line,omitempty"` // The first line of the range for a multi-line comment. + Commit_id string `json:"commit_id"` // The SHA of the commit to which the comment applies. + Start_line int `json:"start_line,omitempty"` // The first line of the range for a multi-line comment. + Updated_at string `json:"updated_at"` + Node_id string `json:"node_id"` // The node ID of the pull request review comment. + Line int `json:"line,omitempty"` // The line of the blob to which the comment applies. The last line of the range for a multi-line comment + Diff_hunk string `json:"diff_hunk"` // The diff of the line that the comment refers to. + Links map[string]interface{} `json:"_links"` + Pull_request_url string `json:"pull_request_url"` // URL for the pull request that the review comment belongs to. + Html_url string `json:"html_url"` // HTML URL for the pull request review comment. + Body string `json:"body"` // The text of the comment. + Start_side string `json:"start_side,omitempty"` // The side of the first line of the range for a multi-line comment. + Path string `json:"path"` // The relative path of the file to which the comment applies. + Id int64 `json:"id"` // The ID of the pull request review comment. + Original_commit_id string `json:"original_commit_id"` // The SHA of the original commit to which the comment applies. + Body_text string `json:"body_text,omitempty"` + Original_position int `json:"original_position,omitempty"` // The index of the original line in the diff to which the comment applies. This field is closing down; use `original_line` instead. + Created_at string `json:"created_at"` + User GeneratedType `json:"user"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Starred_at interface{} `json:"starred_at"` // The time the star was created. This is a timestamp in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. Will be `null` for the `deleted` action. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Permissions string `json:"permissions"` // The permission associated with the invitation. + Expired bool `json:"expired,omitempty"` // Whether or not the invitation has expired + Html_url string `json:"html_url"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Id int64 `json:"id"` // Unique identifier of the repository invitation. + Url string `json:"url"` // URL for the repository invitation + Created_at string `json:"created_at"` + Invitee GeneratedType `json:"invitee"` // A GitHub user. + Inviter GeneratedType `json:"inviter"` // A GitHub user. + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Secret_scanning_non_provider_patterns map[string]interface{} `json:"secret_scanning_non_provider_patterns,omitempty"` + Secret_scanning_push_protection map[string]interface{} `json:"secret_scanning_push_protection,omitempty"` + Advanced_security map[string]interface{} `json:"advanced_security,omitempty"` + Code_security map[string]interface{} `json:"code_security,omitempty"` + Dependabot_security_updates map[string]interface{} `json:"dependabot_security_updates,omitempty"` // Enable or disable Dependabot security updates for the repository. + Secret_scanning map[string]interface{} `json:"secret_scanning,omitempty"` + Secret_scanning_ai_detection map[string]interface{} `json:"secret_scanning_ai_detection,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Start_date string `json:"start_date,omitempty"` + Updated_at string `json:"updated_at"` + Status string `json:"status,omitempty"` + Body string `json:"body,omitempty"` // Body of the status update + Created_at string `json:"created_at"` + Creator GeneratedType `json:"creator,omitempty"` // A GitHub user. + Id float64 `json:"id"` + Node_id string `json:"node_id"` + Project_node_id string `json:"project_node_id,omitempty"` + Target_date string `json:"target_date,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sha string `json:"sha,omitempty"` // SHA of commit with autofix. + Target_ref string `json:"target_ref,omitempty"` // The Git reference of target branch for the commit. For more information, see "[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)" in the Git documentation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` // The changes to the collaborator permissions + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Member Webhooksuser `json:"member"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Cvss_vector_string string `json:"cvss_vector_string,omitempty"` // The CVSS vector that calculates the severity of the advisory. You must choose between setting this field or `severity`. + Description string `json:"description,omitempty"` // A detailed description of what the advisory impacts. + State string `json:"state,omitempty"` // The state of the advisory. + Summary string `json:"summary,omitempty"` // A short summary of the advisory. + Collaborating_teams []string `json:"collaborating_teams,omitempty"` // A list of team slugs which have been granted write access to the advisory. + Cwe_ids []string `json:"cwe_ids,omitempty"` // A list of Common Weakness Enumeration (CWE) IDs. + Vulnerabilities []map[string]interface{} `json:"vulnerabilities,omitempty"` // A product affected by the vulnerability detailed in a repository security advisory. + Collaborating_users []string `json:"collaborating_users,omitempty"` // A list of usernames who have been granted write access to the advisory. + Credits []map[string]interface{} `json:"credits,omitempty"` // A list of users receiving credit for their participation in the security advisory. + Severity string `json:"severity,omitempty"` // The severity of the advisory. You must choose between setting this field or `cvss_vector_string`. + Cve_id string `json:"cve_id,omitempty"` // The Common Vulnerabilities and Exposures (CVE) ID. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Payload string `json:"payload"` // A URL-encoded string of the check_run.requested_action JSON payload. The decoded payload is a JSON object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Registry_package map[string]interface{} `json:"registry_package"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_selection string `json:"repository_selection,omitempty"` // Describe whether all repositories have been selected or there's a selection involved + Single_file string `json:"single_file,omitempty"` + Token string `json:"token"` // The token used for authentication + Expires_at string `json:"expires_at"` // The time this token expires + Permissions map[string]interface{} `json:"permissions,omitempty"` + Repositories []Repository `json:"repositories,omitempty"` // The repositories this token has access to +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url,omitempty"` + Package_html_url string `json:"package_html_url"` + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Id int `json:"id"` // Unique identifier of the package version. + Url string `json:"url"` + Description string `json:"description,omitempty"` + License string `json:"license,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Name string `json:"name"` // The name of the package version. + Deleted_at string `json:"deleted_at,omitempty"` +} + +// Webhooksreview represents the Webhooksreview schema from the OpenAPI specification +type Webhooksreview struct { + Id int `json:"id"` // Unique identifier of the review + Node_id string `json:"node_id"` + Links map[string]interface{} `json:"_links"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Html_url string `json:"html_url"` + Submitted_at string `json:"submitted_at"` + User map[string]interface{} `json:"user"` + Pull_request_url string `json:"pull_request_url"` + State string `json:"state"` + Body string `json:"body"` // The text of the review. + Commit_id string `json:"commit_id"` // A commit SHA for the review. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Repository_ruleset GeneratedType `json:"repository_ruleset"` // A set of rules to apply when specified conditions are met. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// Webhooksrelease1 represents the Webhooksrelease1 schema from the OpenAPI specification +type Webhooksrelease1 struct { + Tarball_url string `json:"tarball_url"` + Target_commitish string `json:"target_commitish"` // Specifies the commitish value that determines where the Git tag is created from. + Url string `json:"url"` + Author map[string]interface{} `json:"author"` + Draft bool `json:"draft"` // Whether the release is a draft or published + Tag_name string `json:"tag_name"` // The name of the tag. + Assets []map[string]interface{} `json:"assets"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Assets_url string `json:"assets_url"` + Prerelease bool `json:"prerelease"` // Whether the release is identified as a prerelease or a full release. + Published_at string `json:"published_at"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + Discussion_url string `json:"discussion_url,omitempty"` + Name string `json:"name"` + Upload_url string `json:"upload_url"` + Body string `json:"body"` + Node_id string `json:"node_id"` + Zipball_url string `json:"zipball_url"` + Html_url string `json:"html_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description,omitempty"` // A short description of the rule used to detect the alert. + Help_uri string `json:"help_uri,omitempty"` // A link to the documentation for the rule used to detect the alert. + Id string `json:"id,omitempty"` // A unique identifier for the rule used to detect the alert. + Name string `json:"name,omitempty"` // The name of the rule used to detect the alert. + Security_severity_level string `json:"security_severity_level,omitempty"` // The security severity of the alert. + Severity string `json:"severity,omitempty"` // The severity of the alert. + Tags []string `json:"tags,omitempty"` // A set of tags applicable for the rule. + Full_description string `json:"full_description,omitempty"` // A description of the rule used to detect the alert. + Help string `json:"help,omitempty"` // Detailed documentation for the rule as GitHub Flavored Markdown. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Environment string `json:"environment,omitempty"` // The name of the environment that has the deployment protection rule. + Event string `json:"event,omitempty"` // The event that triggered the deployment protection rule. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action,omitempty"` + Deployment_callback_url string `json:"deployment_callback_url,omitempty"` // The URL to review the deployment protection rule. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Pull_requests []GeneratedType `json:"pull_requests,omitempty"` + Deployment Deployment `json:"deployment,omitempty"` // A request for a specific ref(branch,sha,tag) to be deployed +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ruleset_id int `json:"ruleset_id,omitempty"` // The ID of the ruleset that includes this rule. + Ruleset_source string `json:"ruleset_source,omitempty"` // The name of the source of the ruleset that includes this rule. + Ruleset_source_type string `json:"ruleset_source_type,omitempty"` // The type of source for the ruleset that includes this rule. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Has_multiple_single_files bool `json:"has_multiple_single_files,omitempty"` + Permissions GeneratedType `json:"permissions"` // The permissions granted to the user access token. + Repositories_url string `json:"repositories_url"` + Repository_selection string `json:"repository_selection"` // Describe whether all repositories have been selected or there's a selection involved + Single_file_name string `json:"single_file_name"` + Single_file_paths []string `json:"single_file_paths,omitempty"` + Account GeneratedType `json:"account"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Committer map[string]interface{} `json:"committer"` // Information about the Git committer + Id string `json:"id"` // SHA for the commit + Message string `json:"message"` // Message describing the purpose of the commit + Timestamp string `json:"timestamp"` // Timestamp of the commit + Tree_id string `json:"tree_id"` // SHA for the commit's tree + Author map[string]interface{} `json:"author"` // Information about the Git author +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Hook map[string]interface{} `json:"hook"` // The deleted webhook. This will contain different keys based on the type of webhook it is: repository, organization, business, app, or GitHub Marketplace. + Hook_id int `json:"hook_id"` // The id of the modified webhook. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Key Webhooksdeploykey `json:"key"` // The [`deploy key`](https://docs.github.com/rest/deploy-keys/deploy-keys#get-a-deploy-key) resource. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // Name of the label. + TypeField string `json:"type,omitempty"` // The type of label. Read-only labels are applied automatically when the runner is configured. + Id int `json:"id,omitempty"` // Unique identifier of the label. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Zen string `json:"zen,omitempty"` // Random string of GitHub zen. + Hook map[string]interface{} `json:"hook,omitempty"` // The webhook that is being pinged + Hook_id int `json:"hook_id,omitempty"` // The ID of the webhook that triggered the ping. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` // The ID of the ruleset + Node_id string `json:"node_id,omitempty"` + Rules []GeneratedType `json:"rules,omitempty"` + Source string `json:"source"` // The name of the source + Enforcement string `json:"enforcement"` // The enforcement level of the ruleset. `evaluate` allows admins to test rules before enforcing them. Admins can view insights on the Rule Insights page (`evaluate` is only available with GitHub Enterprise). + Name string `json:"name"` // The name of the ruleset + Links map[string]interface{} `json:"_links,omitempty"` + Conditions interface{} `json:"conditions,omitempty"` + Bypass_actors []GeneratedType `json:"bypass_actors,omitempty"` // The actors that can bypass the rules in this ruleset + Source_type string `json:"source_type,omitempty"` // The type of the source of the ruleset + Target string `json:"target,omitempty"` // The target of the ruleset + Updated_at string `json:"updated_at,omitempty"` + Created_at string `json:"created_at,omitempty"` + Current_user_can_bypass string `json:"current_user_can_bypass,omitempty"` // The bypass type of the user making the API request for this ruleset. This field is only returned when querying the repository-level endpoint. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Bypass_pull_request_allowances map[string]interface{} `json:"bypass_pull_request_allowances,omitempty"` // Allow specific users, teams, or apps to bypass pull request requirements. + Dismiss_stale_reviews bool `json:"dismiss_stale_reviews"` + Dismissal_restrictions map[string]interface{} `json:"dismissal_restrictions,omitempty"` + Require_code_owner_reviews bool `json:"require_code_owner_reviews"` + Require_last_push_approval bool `json:"require_last_push_approval,omitempty"` // Whether the most recent push must be approved by someone other than the person who pushed it. + Required_approving_review_count int `json:"required_approving_review_count,omitempty"` + Url string `json:"url,omitempty"` +} + +// Verification represents the Verification schema from the OpenAPI specification +type Verification struct { + Verified bool `json:"verified"` + Verified_at string `json:"verified_at"` + Payload string `json:"payload"` + Reason string `json:"reason"` + Signature string `json:"signature"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit map[string]interface{} `json:"commit"` + Content map[string]interface{} `json:"content"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Login string `json:"login"` + Avatar_url string `json:"avatar_url"` + Html_url string `json:"html_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Check_suite map[string]interface{} `json:"check_suite"` // The [check_suite](https://docs.github.com/rest/checks/suites#get-a-check-suite). + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Allow_force_pushes map[string]interface{} `json:"allow_force_pushes,omitempty"` + Block_creations map[string]interface{} `json:"block_creations,omitempty"` + Enforce_admins map[string]interface{} `json:"enforce_admins,omitempty"` + Lock_branch map[string]interface{} `json:"lock_branch,omitempty"` // Whether to set the branch as read-only. If this is true, users will not be able to push to the branch. + Required_pull_request_reviews map[string]interface{} `json:"required_pull_request_reviews,omitempty"` + Required_signatures map[string]interface{} `json:"required_signatures,omitempty"` + Required_conversation_resolution map[string]interface{} `json:"required_conversation_resolution,omitempty"` + Required_linear_history map[string]interface{} `json:"required_linear_history,omitempty"` + Required_status_checks GeneratedType `json:"required_status_checks,omitempty"` // Status Check Policy + Allow_fork_syncing map[string]interface{} `json:"allow_fork_syncing,omitempty"` // Whether users can pull changes from upstream when the branch is locked. Set to `true` to allow fork syncing. Set to `false` to prevent fork syncing. + Restrictions GeneratedType `json:"restrictions,omitempty"` // Branch Restriction Policy + Url string `json:"url"` + Allow_deletions map[string]interface{} `json:"allow_deletions,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor_id int `json:"actor_id,omitempty"` // The number that identifies the user. + Pushed_at string `json:"pushed_at,omitempty"` + Repository_name string `json:"repository_name,omitempty"` // The name of the repository without the `.git` extension. + Result string `json:"result,omitempty"` // The result of the rule evaluations for rules with the `active` enforcement status. + Id int `json:"id,omitempty"` // The unique identifier of the rule insight. + Actor_name string `json:"actor_name,omitempty"` // The handle for the GitHub user account. + After_sha string `json:"after_sha,omitempty"` // The last commit sha in the push evaluation. + Repository_id int `json:"repository_id,omitempty"` // The ID of the repository associated with the rule evaluation. + Before_sha string `json:"before_sha,omitempty"` // The first commit sha before the push evaluation. + Evaluation_result string `json:"evaluation_result,omitempty"` // The result of the rule evaluations for rules with the `active` and `evaluate` enforcement statuses, demonstrating whether rules would pass or fail if all rules in the rule suite were `active`. Null if no rules with `evaluate` enforcement status were run. + Ref string `json:"ref,omitempty"` // The ref name that the evaluation ran on. + Rule_evaluations []map[string]interface{} `json:"rule_evaluations,omitempty"` // Details on the evaluated rules. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Network_configuration_id string `json:"network_configuration_id,omitempty"` // The identifier of a hosted compute network configuration. + Hosted_runners_url string `json:"hosted_runners_url,omitempty"` + Inherited bool `json:"inherited"` + Runners_url string `json:"runners_url"` + Selected_repositories_url string `json:"selected_repositories_url,omitempty"` // Link to the selected repositories resource for this runner group. Not present unless visibility was set to `selected` + Workflow_restrictions_read_only bool `json:"workflow_restrictions_read_only,omitempty"` // If `true`, the `restricted_to_workflows` and `selected_workflows` fields cannot be modified. + Restricted_to_workflows bool `json:"restricted_to_workflows,omitempty"` // If `true`, the runner group will be restricted to running only the workflows specified in the `selected_workflows` array. + Selected_workflows []string `json:"selected_workflows,omitempty"` // List of workflows the runner group should be allowed to run. This setting will be ignored unless `restricted_to_workflows` is set to `true`. + Visibility string `json:"visibility"` + DefaultField bool `json:"default"` + Allows_public_repositories bool `json:"allows_public_repositories"` + Id float64 `json:"id"` + Inherited_allows_public_repositories bool `json:"inherited_allows_public_repositories,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` // The changes to the team if the action was `edited`. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository map[string]interface{} `json:"repository,omitempty"` // A git repository + Sender GeneratedType `json:"sender"` // A GitHub user. + Team Webhooksteam1 `json:"team"` // Groups of organization members that gives permissions on specified repositories. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id string `json:"id"` + Name string `json:"name"` + Color string `json:"color,omitempty"` + Description string `json:"description,omitempty"` +} + +// Installation represents the Installation schema from the OpenAPI specification +type Installation struct { + Repository_selection string `json:"repository_selection"` // Describe whether all repositories have been selected or there's a selection involved + Access_tokens_url string `json:"access_tokens_url"` + Suspended_by GeneratedType `json:"suspended_by"` // A GitHub user. + Single_file_name string `json:"single_file_name"` + Account interface{} `json:"account"` + Html_url string `json:"html_url"` + Contact_email string `json:"contact_email,omitempty"` + App_id int `json:"app_id"` + Updated_at string `json:"updated_at"` + App_slug string `json:"app_slug"` + Events []string `json:"events"` + Has_multiple_single_files bool `json:"has_multiple_single_files,omitempty"` + Target_type string `json:"target_type"` + Permissions GeneratedType `json:"permissions"` // The permissions granted to the user access token. + Repositories_url string `json:"repositories_url"` + Target_id int `json:"target_id"` // The ID of the user or organization this token is being scoped to. + Single_file_paths []string `json:"single_file_paths,omitempty"` + Suspended_at string `json:"suspended_at"` + Created_at string `json:"created_at"` + Id int `json:"id"` // The ID of the installation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + Previous_marketplace_purchase map[string]interface{} `json:"previous_marketplace_purchase,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Action string `json:"action"` + Effective_date string `json:"effective_date"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// Webhooksissue represents the Webhooksissue schema from the OpenAPI specification +type Webhooksissue struct { + User map[string]interface{} `json:"user"` + Repository_url string `json:"repository_url"` + Milestone map[string]interface{} `json:"milestone"` // A collection of related issues and pull requests. + Id int64 `json:"id"` + Comments int `json:"comments"` + State_reason string `json:"state_reason,omitempty"` + Active_lock_reason string `json:"active_lock_reason"` + State string `json:"state,omitempty"` // State of the issue; either 'open' or 'closed' + Performed_via_github_app map[string]interface{} `json:"performed_via_github_app,omitempty"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Comments_url string `json:"comments_url"` + Node_id string `json:"node_id"` + Url string `json:"url"` // URL for the issue + Html_url string `json:"html_url"` + Reactions map[string]interface{} `json:"reactions"` + Body string `json:"body"` // Contents of the issue + Number int `json:"number"` + Sub_issues_summary map[string]interface{} `json:"sub_issues_summary,omitempty"` + Assignees []map[string]interface{} `json:"assignees"` + Labels []map[string]interface{} `json:"labels,omitempty"` + Labels_url string `json:"labels_url"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Events_url string `json:"events_url"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Title string `json:"title"` // Title of the issue + Closed_at string `json:"closed_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Draft bool `json:"draft,omitempty"` + Locked bool `json:"locked,omitempty"` + Assignee map[string]interface{} `json:"assignee,omitempty"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Timeline_url string `json:"timeline_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name pattern that branches or tags must match in order to deploy to the environment. Wildcard characters will not match `/`. For example, to match branches that begin with `release/` and contain an additional single slash, use `release/*/*`. For more information about pattern matching syntax, see the [Ruby File.fnmatch documentation](https://ruby-doc.org/core-2.5.1/File.html#method-c-fnmatch). + TypeField string `json:"type,omitempty"` // Whether this rule targets a branch or tag +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Action string `json:"action"` + Comment Webhookscomment `json:"comment"` + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Marketplace_purchase map[string]interface{} `json:"marketplace_purchase"` + Organization_billing_email string `json:"organization_billing_email,omitempty"` + TypeField string `json:"type"` + Url string `json:"url"` + Email string `json:"email,omitempty"` + Id int `json:"id"` + Login string `json:"login"` + Marketplace_pending_change map[string]interface{} `json:"marketplace_pending_change,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Documentation_url string `json:"documentation_url,omitempty"` + Message string `json:"message,omitempty"` + Schemas []string `json:"schemas,omitempty"` + Scimtype string `json:"scimType,omitempty"` + Status int `json:"status,omitempty"` + Detail string `json:"detail,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Message string `json:"message,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Status string `json:"status,omitempty"` + Documentation_url string `json:"documentation_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes map[string]interface{} `json:"changes"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_card Webhooksprojectcard `json:"project_card"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Commit_url string `json:"commit_url"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Sha string `json:"sha"` + State string `json:"state"` + Statuses []GeneratedType `json:"statuses"` + Total_count int `json:"total_count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow_job map[string]interface{} `json:"workflow_job"` + Action string `json:"action"` + Deployment Deployment `json:"deployment,omitempty"` // A request for a specific ref(branch,sha,tag) to be deployed + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Number int `json:"number"` // The pull request number. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Label Webhookslabel `json:"label,omitempty"` + Pull_request map[string]interface{} `json:"pull_request"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Teams_url string `json:"teams_url"` + Merges_url string `json:"merges_url"` + Blobs_url string `json:"blobs_url"` + Template_repository map[string]interface{} `json:"template_repository,omitempty"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Branches_url string `json:"branches_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Fork bool `json:"fork"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Watchers_count int `json:"watchers_count"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Name string `json:"name"` // The name of the repository. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub user. + Forks_count int `json:"forks_count"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Archive_url string `json:"archive_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Git_url string `json:"git_url"` + Open_issues int `json:"open_issues"` + Contributors_url string `json:"contributors_url"` + Milestones_url string `json:"milestones_url"` + Private bool `json:"private"` // Whether the repository is private or public. + Mirror_url string `json:"mirror_url"` + Labels_url string `json:"labels_url"` + Merge_commit_message string `json:"merge_commit_message,omitempty"` // The default value for a merge commit message. - `PR_TITLE` - default to the pull request's title. - `PR_BODY` - default to the pull request's body. - `BLANK` - default to a blank commit message. + Comments_url string `json:"comments_url"` + Stargazers_url string `json:"stargazers_url"` + Stargazers_count int `json:"stargazers_count"` + Keys_url string `json:"keys_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Git_refs_url string `json:"git_refs_url"` + Collaborators_url string `json:"collaborators_url"` + License GeneratedType `json:"license"` // License Simple + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + Issues_url string `json:"issues_url"` + Git_commits_url string `json:"git_commits_url"` + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Forks_url string `json:"forks_url"` + Merge_commit_title string `json:"merge_commit_title,omitempty"` // The default value for a merge commit title. - `PR_TITLE` - default to the pull request's title. - `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name). + Allow_update_branch bool `json:"allow_update_branch,omitempty"` // Whether or not a pull request head branch that is behind its base branch can always be updated even if it is not required to be up to date before merging. + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Releases_url string `json:"releases_url"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Node_id string `json:"node_id"` + Master_branch string `json:"master_branch,omitempty"` + Watchers int `json:"watchers"` + Html_url string `json:"html_url"` + Size int `json:"size"` // The size of the repository, in kilobytes. Size is calculated hourly. When a repository is initially created, the size is 0. + Permissions map[string]interface{} `json:"permissions,omitempty"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Pushed_at string `json:"pushed_at"` + Custom_properties map[string]interface{} `json:"custom_properties,omitempty"` // The custom properties that were defined for the repository. The keys are the custom property names, and the values are the corresponding custom property values. + Squash_merge_commit_message string `json:"squash_merge_commit_message,omitempty"` // The default value for a squash merge commit message: - `PR_BODY` - default to the pull request's body. - `COMMIT_MESSAGES` - default to the branch's commit messages. - `BLANK` - default to a blank commit message. + Ssh_url string `json:"ssh_url"` + Downloads_url string `json:"downloads_url"` + Network_count int `json:"network_count,omitempty"` + Pulls_url string `json:"pulls_url"` + Languages_url string `json:"languages_url"` + Forks int `json:"forks"` + Commits_url string `json:"commits_url"` + Description string `json:"description"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Svn_url string `json:"svn_url"` + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Updated_at string `json:"updated_at"` + Full_name string `json:"full_name"` + Language string `json:"language"` + Id int64 `json:"id"` // Unique identifier of the repository + Contents_url string `json:"contents_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Statuses_url string `json:"statuses_url"` + Events_url string `json:"events_url"` + Issue_comment_url string `json:"issue_comment_url"` + Subscription_url string `json:"subscription_url"` + Hooks_url string `json:"hooks_url"` + Open_issues_count int `json:"open_issues_count"` + Tags_url string `json:"tags_url"` + Squash_merge_commit_title string `json:"squash_merge_commit_title,omitempty"` // The default value for a squash merge commit title: - `PR_TITLE` - default to the pull request's title. - `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit). + Has_pages bool `json:"has_pages"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` // Whether a squash merge commit can use the pull request title as default. **This property is closing down. Please use `squash_merge_commit_title` instead. + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Homepage string `json:"homepage"` + Topics []string `json:"topics,omitempty"` + Compare_url string `json:"compare_url"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Assignees_url string `json:"assignees_url"` + Notifications_url string `json:"notifications_url"` + Deployments_url string `json:"deployments_url"` + Subscribers_url string `json:"subscribers_url"` + Starred_at string `json:"starred_at,omitempty"` + Trees_url string `json:"trees_url"` + Issue_events_url string `json:"issue_events_url"` + Clone_url string `json:"clone_url"` + Git_tags_url string `json:"git_tags_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Html_url string `json:"html_url"` + Key string `json:"key"` + Name string `json:"name"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Current_user_can_approve bool `json:"current_user_can_approve"` // Whether the currently authenticated user can approve the deployment + Environment map[string]interface{} `json:"environment"` + Reviewers []map[string]interface{} `json:"reviewers"` // The people or teams that may approve jobs that reference the environment. You can list up to six users or teams as reviewers. The reviewers must have at least read access to the repository. Only one of the required reviewers needs to approve the job for it to proceed. + Wait_timer int `json:"wait_timer"` // The set duration of the wait timer + Wait_timer_started_at string `json:"wait_timer_started_at"` // The time that the wait timer began. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + New_property_values []GeneratedType `json:"new_property_values"` // The new custom property values for the repository. + Old_property_values []GeneratedType `json:"old_property_values"` // The old custom property values for the repository. + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ref string `json:"ref"` + Url string `json:"url"` + Node_id string `json:"node_id"` + Object map[string]interface{} `json:"object"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Completed_at string `json:"completed_at"` + Output map[string]interface{} `json:"output"` + Status string `json:"status"` // The phase of the lifecycle that the check is currently in. + Url string `json:"url"` + Node_id string `json:"node_id"` + Html_url string `json:"html_url"` + Pull_requests []GeneratedType `json:"pull_requests"` + Name string `json:"name"` // The name of the check. + External_id string `json:"external_id"` + Started_at string `json:"started_at"` + Head_sha string `json:"head_sha"` // The SHA of the commit that is being checked. + Conclusion string `json:"conclusion"` + App Integration `json:"app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Details_url string `json:"details_url"` + Check_suite GeneratedType `json:"check_suite"` // A suite of checks performed on the code of a given code change + Deployment GeneratedType `json:"deployment,omitempty"` // A deployment created as the result of an Actions check run from a workflow that references an environment + Id int `json:"id"` // The id of the check. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Membership Webhooksmembership `json:"membership,omitempty"` // The membership between the user and the organization. Not present when the action is `member_invited`. + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the repository property to target + Property_values []string `json:"property_values"` // The values to match for the repository property + Source string `json:"source,omitempty"` // The source of the repository property. Defaults to 'custom' if not specified. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Assigner GeneratedType `json:"assigner"` // A GitHub user. + Commit_url string `json:"commit_url"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Created_at string `json:"created_at"` + Event string `json:"event"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Performed_via_github_app Integration `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Commit_id string `json:"commit_id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Message string `json:"message"` // Message describing the purpose of the commit + Timestamp string `json:"timestamp"` // Timestamp of the commit + Tree_id string `json:"tree_id"` // SHA for the commit's tree + Author map[string]interface{} `json:"author"` // Information about the Git author + Committer map[string]interface{} `json:"committer"` // Information about the Git committer + Id string `json:"id"` // SHA for the commit +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Version_id int `json:"version_id"` // The ID of the previous version of the ruleset + Actor map[string]interface{} `json:"actor"` // The actor who updated the ruleset +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Member Webhooksuser `json:"member"` + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Scope string `json:"scope"` // The scope of the membership. Currently, can only be `team`. + Sender map[string]interface{} `json:"sender"` + Team Webhooksteam `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_url string `json:"repository_url"` + Subscribed bool `json:"subscribed"` // Determines if notifications should be received from this repository. + Url string `json:"url"` + Created_at string `json:"created_at"` + Ignored bool `json:"ignored"` // Determines if all notifications should be blocked from this repository. + Reason string `json:"reason"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_on string `json:"created_on"` // The time at which the network configuration was created, in ISO 8601 format. + Id string `json:"id"` // The unique identifier of the network configuration. + Name string `json:"name"` // The name of the network configuration. + Network_settings_ids []string `json:"network_settings_ids,omitempty"` // The unique identifier of each network settings in the configuration. + Compute_service string `json:"compute_service,omitempty"` // The hosted compute service the network configuration supports. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Project_card Webhooksprojectcard `json:"project_card"` + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Label Webhookslabel `json:"label"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Access_level string `json:"access_level"` // Defines the level of access that workflows outside of the repository have to actions and reusable workflows within the repository. `none` means the access is only possible from workflows in this repository. `user` level access allows sharing across user owned private repositories only. `organization` level access allows sharing across the organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Effective_date string `json:"effective_date,omitempty"` // The `pending_cancellation` and `pending_tier_change` event types will include the date the cancellation or tier change will take effect. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Sponsorship Webhookssponsorship `json:"sponsorship"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Percentile float64 `json:"percentile,omitempty"` + Percentage float64 `json:"percentage,omitempty"` +} + +// Webhooksmembership represents the Webhooksmembership schema from the OpenAPI specification +type Webhooksmembership struct { + Organization_url string `json:"organization_url"` + Role string `json:"role"` + State string `json:"state"` + Url string `json:"url"` + User map[string]interface{} `json:"user"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Personal_access_token_request GeneratedType `json:"personal_access_token_request"` // Details of a Personal Access Token Request. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes,omitempty"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Repository_ruleset GeneratedType `json:"repository_ruleset"` // A set of rules to apply when specified conditions are met. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Node_id string `json:"node_id"` + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Id int `json:"id"` + Project_card map[string]interface{} `json:"project_card,omitempty"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_id string `json:"commit_id"` + Performed_via_github_app Integration `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Payload string `json:"payload"` // A URL-encoded string of the secret_scanning_alert_location.created JSON payload. The decoded payload is a JSON object. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` // Unique identifier of the GitHub app + Installations_count int `json:"installations_count,omitempty"` // The number of installations associated with the GitHub app. Only returned when the integration is requesting details about itself. + Owner interface{} `json:"owner"` + Html_url string `json:"html_url"` + Name string `json:"name"` // The name of the GitHub app + Node_id string `json:"node_id"` + Permissions map[string]interface{} `json:"permissions"` // The set of permissions for the GitHub app + Slug string `json:"slug,omitempty"` // The slug name of the GitHub app + Created_at string `json:"created_at"` + Description string `json:"description"` + Events []string `json:"events"` // The list of events for the GitHub app. Note that the `installation_target`, `security_advisory`, and `meta` events are not included because they are global events and not specific to an installation. + External_url string `json:"external_url"` + Client_id string `json:"client_id,omitempty"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id,omitempty"` // The unique identifier of the branch or tag policy. + Name string `json:"name,omitempty"` // The name pattern that branches or tags must match in order to deploy to the environment. + Node_id string `json:"node_id,omitempty"` + TypeField string `json:"type,omitempty"` // Whether this rule targets a branch or tag. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Color string `json:"color,omitempty"` // Color for the issue type. + Description string `json:"description,omitempty"` // Description of the issue type. + Is_enabled bool `json:"is_enabled"` // Whether or not the issue type is enabled at the organization level. + Name string `json:"name"` // Name of the issue type. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_selection string `json:"repository_selection"` // Type of repository selection requested. + Token_expires_at string `json:"token_expires_at"` // Date and time when the associated fine-grained personal access token expires. + Token_id int `json:"token_id"` // Unique identifier of the user's token. This field can also be found in audit log events and the organization's settings for their PAT grants. + Token_last_used_at string `json:"token_last_used_at"` // Date and time when the associated fine-grained personal access token was last used for authentication. + Permissions_result map[string]interface{} `json:"permissions_result"` // Permissions requested, categorized by type of permission. This field incorporates `permissions_added` and `permissions_upgraded`. + Repositories []map[string]interface{} `json:"repositories"` // An array of repository objects the token is requesting access to. This field is only populated when `repository_selection` is `subset`. + Repository_count int `json:"repository_count"` // The number of repositories the token is requesting access to. This field is only populated when `repository_selection` is `subset`. + Token_name string `json:"token_name"` // The name given to the user's token. This field can also be found in an organization's settings page for Active Tokens. + Created_at string `json:"created_at"` // Date and time when the request for access was created. + Owner GeneratedType `json:"owner"` // A GitHub user. + Id int `json:"id"` // Unique identifier of the request for access via fine-grained personal access token. Used as the `pat_request_id` parameter in the list and review API calls. + Permissions_upgraded map[string]interface{} `json:"permissions_upgraded"` // Requested permissions that elevate access for a previously approved request for access, categorized by type of permission. + Token_expired bool `json:"token_expired"` // Whether the associated fine-grained personal access token has expired. + Permissions_added map[string]interface{} `json:"permissions_added"` // New requested permissions, categorized by type of permission. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + Definition GeneratedType `json:"definition"` // Custom property defined on an organization + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_id string `json:"commit_id"` + Milestone map[string]interface{} `json:"milestone"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Url string `json:"url"` + Event string `json:"event"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // Minimal Repository + Status string `json:"status"` // The phase of the lifecycle that the check suite is currently in. Statuses of waiting, requested, and pending are reserved for GitHub Actions check suites. + Updated_at string `json:"updated_at"` + Url string `json:"url"` + After string `json:"after"` + Runs_rerequestable bool `json:"runs_rerequestable,omitempty"` + App GeneratedType `json:"app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Conclusion string `json:"conclusion"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Id int64 `json:"id"` + Pull_requests []GeneratedType `json:"pull_requests"` + Head_sha string `json:"head_sha"` // The SHA of the head commit that is being checked. + Before string `json:"before"` + Rerequestable bool `json:"rerequestable,omitempty"` + Head_branch string `json:"head_branch"` + Head_commit GeneratedType `json:"head_commit"` // A commit. + Check_runs_url string `json:"check_runs_url"` + Latest_check_runs_count int `json:"latest_check_runs_count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Changes interface{} `json:"changes,omitempty"` // The changes made to the item may involve modifications in the item's fields and draft issue body. It includes altered values for text, number, date, single select, and iteration fields, along with the GraphQL node ID of the changed field. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Projects_v2_item GeneratedType `json:"projects_v2_item"` // An item belonging to a project +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actor GeneratedType `json:"actor"` // A GitHub user. + Id int `json:"id"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Label map[string]interface{} `json:"label"` + Performed_via_github_app GeneratedType `json:"performed_via_github_app"` // GitHub apps are a new way to extend GitHub. They can be installed directly on organizations and user accounts and granted access to specific repositories. They come with granular permissions and built-in webhooks. GitHub apps are first class actors within GitHub. + Commit_id string `json:"commit_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Token_type string `json:"token_type,omitempty"` // The token type this bypass is for. + Expire_at string `json:"expire_at,omitempty"` // The time that the bypass will expire in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Reason string `json:"reason,omitempty"` // The reason for bypassing push protection. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Pusher map[string]interface{} `json:"pusher"` // Metaproperties for Git author/committer information. + Before string `json:"before"` // The SHA of the most recent commit on `ref` before the push. + Deleted bool `json:"deleted"` // Whether this push deleted the `ref`. + Repository map[string]interface{} `json:"repository"` // A git repository + Created bool `json:"created"` // Whether this push created the `ref`. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Commits []map[string]interface{} `json:"commits"` // An array of commit objects describing the pushed commits. (Pushed commits are all commits that are included in the `compare` between the `before` commit and the `after` commit.) The array includes a maximum of 2048 commits. If necessary, you can use the [Commits API](https://docs.github.com/rest/commits) to fetch additional commits. + Ref string `json:"ref"` // The full git ref that was pushed. Example: `refs/heads/main` or `refs/tags/v3.14.1`. + Base_ref string `json:"base_ref"` + Compare string `json:"compare"` // URL that shows the changes in this `ref` update, from the `before` commit to the `after` commit. For a newly created `ref` that is directly based on the default branch, this is the comparison between the head of the default branch and the `after` commit. Otherwise, this shows all commits until the `after` commit. + Forced bool `json:"forced"` // Whether this push was a force push of the `ref`. + Head_commit map[string]interface{} `json:"head_commit"` + After string `json:"after"` // The SHA of the most recent commit on `ref` after the push. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Query_language string `json:"query_language"` // The language targeted by the CodeQL query + Skipped_repositories map[string]interface{} `json:"skipped_repositories,omitempty"` // Information about repositories that were skipped from processing. This information is only available to the user that initiated the variant analysis. + Actions_workflow_run_id int `json:"actions_workflow_run_id,omitempty"` // The GitHub Actions workflow run used to execute this variant analysis. This is only available if the workflow run has started. + Completed_at string `json:"completed_at,omitempty"` // The date and time at which the variant analysis was completed, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. Will be null if the variant analysis has not yet completed or this information is not available. + Created_at string `json:"created_at,omitempty"` // The date and time at which the variant analysis was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Status string `json:"status"` + Failure_reason string `json:"failure_reason,omitempty"` // The reason for a failure of the variant analysis. This is only available if the variant analysis has failed. + Id int `json:"id"` // The ID of the variant analysis. + Updated_at string `json:"updated_at,omitempty"` // The date and time at which the variant analysis was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Query_pack_url string `json:"query_pack_url"` // The download url for the query pack. + Scanned_repositories []map[string]interface{} `json:"scanned_repositories,omitempty"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Controller_repo GeneratedType `json:"controller_repo"` // A GitHub repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Security_advisory map[string]interface{} `json:"security_advisory"` // The details of the security advisory, including summary, description, and severity. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Documentation_url string `json:"documentation_url,omitempty"` + Message string `json:"message,omitempty"` + Status string `json:"status,omitempty"` + Url string `json:"url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Links map[string]interface{} `json:"_links"` + Download_url string `json:"download_url"` + Html_url string `json:"html_url"` + Path string `json:"path"` + Submodule_git_url string `json:"submodule_git_url"` + Git_url string `json:"git_url"` + Name string `json:"name"` + Sha string `json:"sha"` + Size int `json:"size"` + TypeField string `json:"type"` + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Issue_body_url string `json:"issue_body_url"` // The API URL to get the issue where the secret was detected. +} + +// Webhooksapprover represents the Webhooksapprover schema from the OpenAPI specification +type Webhooksapprover struct { + Login string `json:"login,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Followers_url string `json:"followers_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + Id int `json:"id,omitempty"` + Repos_url string `json:"repos_url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + TypeField string `json:"type,omitempty"` + Url string `json:"url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Events_url string `json:"events_url,omitempty"` + Gists_url string `json:"gists_url,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Comment Webhookscomment `json:"comment"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Html_url string `json:"html_url"` + Size int `json:"size"` + Target string `json:"target"` + TypeField string `json:"type"` + Links map[string]interface{} `json:"_links"` + Git_url string `json:"git_url"` + Sha string `json:"sha"` + Download_url string `json:"download_url"` + Name string `json:"name"` + Path string `json:"path"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository GeneratedType `json:"repository"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Issue Webhooksissue2 `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` // The node ID for the deployment protection rule. + App GeneratedType `json:"app"` // A GitHub App that is providing a custom deployment protection rule. + Enabled bool `json:"enabled"` // Whether the deployment protection rule is enabled for the environment. + Id int `json:"id"` // The unique identifier for the deployment protection rule. +} + +// Metadata represents the Metadata schema from the OpenAPI specification +type Metadata struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Effective_date string `json:"effective_date"` + Enterprise GeneratedType `json:"enterprise,omitempty"` // An enterprise on GitHub. Webhook payloads contain the `enterprise` property when the webhook is configured on an enterprise account or an organization that's part of an enterprise account. For more information, see "[About enterprise accounts](https://docs.github.com/admin/overview/about-enterprise-accounts)." + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + Previous_marketplace_purchase map[string]interface{} `json:"previous_marketplace_purchase,omitempty"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. Webhook payloads contain the `organization` property when the webhook is configured for an organization, or when the event occurs from activity in a repository owned by an organization. + Installation GeneratedType `json:"installation,omitempty"` // The GitHub App installation. Webhook payloads contain the `installation` property when the event is configured for and sent to a GitHub App. For more information, see "[Using webhooks with GitHub Apps](https://docs.github.com/apps/creating-github-apps/registering-a-github-app/using-webhooks-with-github-apps)." + Repository GeneratedType `json:"repository,omitempty"` // The repository on GitHub where the event occurred. Webhook payloads contain the `repository` property when the event occurs from activity in a repository. +} diff --git a/MCP/registry.go b/MCP/registry.go new file mode 100644 index 0000000..042fea6 --- /dev/null +++ b/MCP/registry.go @@ -0,0 +1,1085 @@ +package main + +import ( + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + tools_repos "github.com/github-v3-rest-api/mcp-server/tools/repos" + tools_actions "github.com/github-v3-rest-api/mcp-server/tools/actions" + tools_codespaces "github.com/github-v3-rest-api/mcp-server/tools/codespaces" + tools_apps "github.com/github-v3-rest-api/mcp-server/tools/apps" + tools_teams "github.com/github-v3-rest-api/mcp-server/tools/teams" + tools_code_scanning "github.com/github-v3-rest-api/mcp-server/tools/code_scanning" + tools_rate_limit "github.com/github-v3-rest-api/mcp-server/tools/rate_limit" + tools_dependabot "github.com/github-v3-rest-api/mcp-server/tools/dependabot" + tools_pulls "github.com/github-v3-rest-api/mcp-server/tools/pulls" + tools_activity "github.com/github-v3-rest-api/mcp-server/tools/activity" + tools_issues "github.com/github-v3-rest-api/mcp-server/tools/issues" + tools_orgs "github.com/github-v3-rest-api/mcp-server/tools/orgs" + tools_meta "github.com/github-v3-rest-api/mcp-server/tools/meta" + tools_dependency_graph "github.com/github-v3-rest-api/mcp-server/tools/dependency_graph" + tools_users "github.com/github-v3-rest-api/mcp-server/tools/users" + tools_projects "github.com/github-v3-rest-api/mcp-server/tools/projects" + tools_security_advisories "github.com/github-v3-rest-api/mcp-server/tools/security_advisories" + tools_packages "github.com/github-v3-rest-api/mcp-server/tools/packages" + tools_copilot "github.com/github-v3-rest-api/mcp-server/tools/copilot" + tools_reactions "github.com/github-v3-rest-api/mcp-server/tools/reactions" + tools_checks "github.com/github-v3-rest-api/mcp-server/tools/checks" + tools_gitignore "github.com/github-v3-rest-api/mcp-server/tools/gitignore" + tools_migrations "github.com/github-v3-rest-api/mcp-server/tools/migrations" + tools_private_registries "github.com/github-v3-rest-api/mcp-server/tools/private_registries" + tools_git "github.com/github-v3-rest-api/mcp-server/tools/git" + tools_credentials "github.com/github-v3-rest-api/mcp-server/tools/credentials" + tools_secret_scanning "github.com/github-v3-rest-api/mcp-server/tools/secret_scanning" + tools_classroom "github.com/github-v3-rest-api/mcp-server/tools/classroom" + tools_billing "github.com/github-v3-rest-api/mcp-server/tools/billing" + tools_code_security "github.com/github-v3-rest-api/mcp-server/tools/code_security" + tools_emojis "github.com/github-v3-rest-api/mcp-server/tools/emojis" + tools_search "github.com/github-v3-rest-api/mcp-server/tools/search" + tools_gists "github.com/github-v3-rest-api/mcp-server/tools/gists" + tools_interactions "github.com/github-v3-rest-api/mcp-server/tools/interactions" + tools_oidc "github.com/github-v3-rest-api/mcp-server/tools/oidc" + tools_hosted_compute "github.com/github-v3-rest-api/mcp-server/tools/hosted_compute" + tools_codes_of_conduct "github.com/github-v3-rest-api/mcp-server/tools/codes_of_conduct" + tools_campaigns "github.com/github-v3-rest-api/mcp-server/tools/campaigns" + tools_licenses "github.com/github-v3-rest-api/mcp-server/tools/licenses" +) + +func GetAll(cfg *config.APIConfig) []models.Tool { + return []models.Tool{ + tools_repos.CreateRepos_disable_vulnerability_alertsTool(cfg), + tools_repos.CreateRepos_check_vulnerability_alertsTool(cfg), + tools_repos.CreateRepos_enable_vulnerability_alertsTool(cfg), + tools_actions.CreateActions_set_workflow_access_to_repositoryTool(cfg), + tools_actions.CreateActions_get_workflow_access_to_repositoryTool(cfg), + tools_repos.CreateRepos_generate_release_notesTool(cfg), + tools_codespaces.CreateCodespaces_publish_for_authenticated_userTool(cfg), + tools_apps.CreateApps_delete_installationTool(cfg), + tools_apps.CreateApps_get_installationTool(cfg), + tools_teams.CreateTeams_list_discussions_legacyTool(cfg), + tools_teams.CreateTeams_create_discussion_legacyTool(cfg), + tools_code_scanning.CreateCode_scanning_get_autofixTool(cfg), + tools_code_scanning.CreateCode_scanning_create_autofixTool(cfg), + tools_teams.CreateTeams_list_child_in_orgTool(cfg), + tools_codespaces.CreateCodespaces_delete_repo_secretTool(cfg), + tools_codespaces.CreateCodespaces_get_repo_secretTool(cfg), + tools_codespaces.CreateCodespaces_create_or_update_repo_secretTool(cfg), + tools_actions.CreateActions_delete_workflow_runTool(cfg), + tools_actions.CreateActions_get_workflow_runTool(cfg), + tools_rate_limit.CreateRate_limit_getTool(cfg), + tools_actions.CreateActions_delete_workflow_run_logsTool(cfg), + tools_actions.CreateActions_download_workflow_run_logsTool(cfg), + tools_dependabot.CreateDependabot_list_alerts_for_enterpriseTool(cfg), + tools_actions.CreateActions_list_workflow_run_artifactsTool(cfg), + tools_pulls.CreatePulls_list_filesTool(cfg), + tools_activity.CreateActivity_list_watched_repos_for_authenticated_userTool(cfg), + tools_issues.CreateIssues_list_for_orgTool(cfg), + tools_repos.CreateRepos_get_punch_card_statsTool(cfg), + tools_teams.CreateTeams_delete_discussion_legacyTool(cfg), + tools_teams.CreateTeams_get_discussion_legacyTool(cfg), + tools_teams.CreateTeams_update_discussion_legacyTool(cfg), + tools_orgs.CreateOrgs_list_for_userTool(cfg), + tools_meta.CreateMeta_rootTool(cfg), + tools_actions.CreateActions_disable_selected_repository_github_actions_organizationTool(cfg), + tools_actions.CreateActions_enable_selected_repository_github_actions_organizationTool(cfg), + tools_issues.CreateIssues_list_events_for_repoTool(cfg), + tools_repos.CreateRepos_get_code_frequency_statsTool(cfg), + tools_issues.CreateIssues_list_for_repoTool(cfg), + tools_issues.CreateIssues_createTool(cfg), + tools_dependabot.CreateDependabot_get_alertTool(cfg), + tools_dependabot.CreateDependabot_update_alertTool(cfg), + tools_dependency_graph.CreateDependency_graph_diff_rangeTool(cfg), + tools_users.CreateUsers_get_context_for_userTool(cfg), + tools_repos.CreateRepos_create_commit_statusTool(cfg), + tools_projects.CreateProjects_list_collaboratorsTool(cfg), + tools_activity.CreateActivity_list_public_org_eventsTool(cfg), + tools_actions.CreateActions_download_job_logs_for_workflow_runTool(cfg), + tools_repos.CreateRepos_get_custom_properties_valuesTool(cfg), + tools_repos.CreateRepos_create_or_update_custom_properties_valuesTool(cfg), + tools_security_advisories.CreateSecurity_advisories_get_repository_advisoryTool(cfg), + tools_security_advisories.CreateSecurity_advisories_update_repository_advisoryTool(cfg), + tools_actions.CreateActions_re_run_workflowTool(cfg), + tools_packages.CreatePackages_get_all_package_versions_for_package_owned_by_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_list_custom_properties_values_for_reposTool(cfg), + tools_orgs.CreateOrgs_create_or_update_custom_properties_values_for_reposTool(cfg), + tools_repos.CreateRepos_get_commit_activity_statsTool(cfg), + tools_actions.CreateActions_get_actions_cache_usage_for_orgTool(cfg), + tools_repos.CreateRepos_list_activitiesTool(cfg), + tools_codespaces.CreateCodespaces_list_org_secretsTool(cfg), + tools_actions.CreateActions_generate_runner_jitconfig_for_repoTool(cfg), + tools_apps.CreateApps_get_by_slugTool(cfg), + tools_orgs.CreateOrgs_remove_public_membership_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_check_public_membership_for_userTool(cfg), + tools_orgs.CreateOrgs_set_public_membership_for_authenticated_userTool(cfg), + tools_projects.CreateProjects_remove_collaboratorTool(cfg), + tools_projects.CreateProjects_add_collaboratorTool(cfg), + tools_actions.CreateActions_remove_self_hosted_runner_from_group_for_orgTool(cfg), + tools_actions.CreateActions_add_self_hosted_runner_to_group_for_orgTool(cfg), + tools_actions.CreateActions_delete_artifactTool(cfg), + tools_actions.CreateActions_get_artifactTool(cfg), + tools_copilot.CreateCopilot_cancel_copilot_seat_assignment_for_usersTool(cfg), + tools_copilot.CreateCopilot_add_copilot_seats_for_usersTool(cfg), + tools_reactions.CreateReactions_delete_for_issue_commentTool(cfg), + tools_activity.CreateActivity_list_received_public_events_for_userTool(cfg), + tools_code_scanning.CreateCode_scanning_delete_codeql_databaseTool(cfg), + tools_code_scanning.CreateCode_scanning_get_codeql_databaseTool(cfg), + tools_users.CreateUsers_list_ssh_signing_keys_for_authenticated_userTool(cfg), + tools_users.CreateUsers_create_ssh_signing_key_for_authenticated_userTool(cfg), + tools_pulls.CreatePulls_get_review_commentTool(cfg), + tools_pulls.CreatePulls_update_review_commentTool(cfg), + tools_pulls.CreatePulls_delete_review_commentTool(cfg), + tools_repos.CreateRepos_delete_deployment_branch_policyTool(cfg), + tools_repos.CreateRepos_get_deployment_branch_policyTool(cfg), + tools_repos.CreateRepos_update_deployment_branch_policyTool(cfg), + tools_dependabot.CreateDependabot_list_alerts_for_orgTool(cfg), + tools_orgs.CreateOrgs_get_org_ruleset_versionTool(cfg), + tools_checks.CreateChecks_rerequest_runTool(cfg), + tools_gitignore.CreateGitignore_get_all_templatesTool(cfg), + tools_actions.CreateActions_get_job_for_workflow_runTool(cfg), + tools_users.CreateUsers_get_by_idTool(cfg), + tools_code_scanning.CreateCode_scanning_get_alertTool(cfg), + tools_code_scanning.CreateCode_scanning_update_alertTool(cfg), + tools_orgs.CreateOrgs_enable_or_disable_security_product_on_all_org_reposTool(cfg), + tools_orgs.CreateOrgs_get_all_custom_propertiesTool(cfg), + tools_orgs.CreateOrgs_create_or_update_custom_propertiesTool(cfg), + tools_users.CreateUsers_delete_email_for_authenticated_userTool(cfg), + tools_users.CreateUsers_list_emails_for_authenticated_userTool(cfg), + tools_users.CreateUsers_add_email_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_tagsTool(cfg), + tools_codespaces.CreateCodespaces_set_codespaces_accessTool(cfg), + tools_migrations.CreateMigrations_delete_archive_for_authenticated_userTool(cfg), + tools_migrations.CreateMigrations_get_archive_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_get_all_package_versions_for_package_owned_by_orgTool(cfg), + tools_actions.CreateActions_list_jobs_for_workflow_run_attemptTool(cfg), + tools_codespaces.CreateCodespaces_check_permissions_for_devcontainerTool(cfg), + tools_orgs.CreateOrgs_revoke_all_org_roles_teamTool(cfg), + tools_issues.CreateIssues_remove_assigneesTool(cfg), + tools_issues.CreateIssues_add_assigneesTool(cfg), + tools_codespaces.CreateCodespaces_delete_codespaces_access_usersTool(cfg), + tools_codespaces.CreateCodespaces_set_codespaces_access_usersTool(cfg), + tools_private_registries.CreatePrivate_registries_list_org_private_registriesTool(cfg), + tools_private_registries.CreatePrivate_registries_create_org_private_registryTool(cfg), + tools_git.CreateGit_delete_refTool(cfg), + tools_git.CreateGit_update_refTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_legacyTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_legacyTool(cfg), + tools_credentials.CreateCredentials_revokeTool(cfg), + tools_apps.CreateApps_unsuspend_installationTool(cfg), + tools_apps.CreateApps_suspend_installationTool(cfg), + tools_code_scanning.CreateCode_scanning_list_alert_instancesTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_locations_for_alertTool(cfg), + tools_classroom.CreateClassroom_get_assignment_gradesTool(cfg), + tools_checks.CreateChecks_list_for_suiteTool(cfg), + tools_reactions.CreateReactions_list_for_issue_commentTool(cfg), + tools_reactions.CreateReactions_create_for_issue_commentTool(cfg), + tools_pulls.CreatePulls_check_if_mergedTool(cfg), + tools_pulls.CreatePulls_mergeTool(cfg), + tools_repos.CreateRepos_list_publicTool(cfg), + tools_repos.CreateRepos_list_deployment_branch_policiesTool(cfg), + tools_repos.CreateRepos_create_deployment_branch_policyTool(cfg), + tools_reactions.CreateReactions_delete_for_team_discussion_commentTool(cfg), + tools_repos.CreateRepos_list_deploy_keysTool(cfg), + tools_repos.CreateRepos_create_deploy_keyTool(cfg), + tools_reactions.CreateReactions_delete_for_pull_request_commentTool(cfg), + tools_dependabot.CreateDependabot_list_selected_repos_for_org_secretTool(cfg), + tools_dependabot.CreateDependabot_set_selected_repos_for_org_secretTool(cfg), + tools_migrations.CreateMigrations_get_status_for_authenticated_userTool(cfg), + tools_billing.CreateBilling_get_github_actions_billing_userTool(cfg), + tools_actions.CreateActions_delete_actions_cache_by_idTool(cfg), + tools_code_security.CreateCode_security_get_configurations_for_orgTool(cfg), + tools_code_security.CreateCode_security_create_configurationTool(cfg), + tools_git.CreateGit_create_commitTool(cfg), + tools_teams.CreateTeams_remove_member_legacyTool(cfg), + tools_teams.CreateTeams_get_member_legacyTool(cfg), + tools_teams.CreateTeams_add_member_legacyTool(cfg), + tools_issues.CreateIssues_list_labels_for_repoTool(cfg), + tools_issues.CreateIssues_create_labelTool(cfg), + tools_copilot.CreateCopilot_copilot_metrics_for_teamTool(cfg), + tools_orgs.CreateOrgs_remove_security_manager_teamTool(cfg), + tools_orgs.CreateOrgs_add_security_manager_teamTool(cfg), + tools_code_scanning.CreateCode_scanning_commit_autofixTool(cfg), + tools_codespaces.CreateCodespaces_get_codespaces_for_user_in_orgTool(cfg), + tools_packages.CreatePackages_get_package_version_for_userTool(cfg), + tools_packages.CreatePackages_delete_package_version_for_userTool(cfg), + tools_repos.CreateRepos_get_commitTool(cfg), + tools_repos.CreateRepos_update_org_rulesetTool(cfg), + tools_repos.CreateRepos_delete_org_rulesetTool(cfg), + tools_repos.CreateRepos_get_org_rulesetTool(cfg), + tools_activity.CreateActivity_delete_repo_subscriptionTool(cfg), + tools_activity.CreateActivity_get_repo_subscriptionTool(cfg), + tools_activity.CreateActivity_set_repo_subscriptionTool(cfg), + tools_users.CreateUsers_list_gpg_keys_for_authenticated_userTool(cfg), + tools_users.CreateUsers_create_gpg_key_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_org_secretsTool(cfg), + tools_orgs.CreateOrgs_remove_custom_propertyTool(cfg), + tools_orgs.CreateOrgs_get_custom_propertyTool(cfg), + tools_orgs.CreateOrgs_create_or_update_custom_propertyTool(cfg), + tools_checks.CreateChecks_get_suiteTool(cfg), + tools_apps.CreateApps_update_webhook_config_for_appTool(cfg), + tools_apps.CreateApps_get_webhook_config_for_appTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_comment_legacyTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_comment_legacyTool(cfg), + tools_repos.CreateRepos_get_repo_rulesetsTool(cfg), + tools_repos.CreateRepos_create_repo_rulesetTool(cfg), + tools_dependabot.CreateDependabot_set_repository_access_default_levelTool(cfg), + tools_repos.CreateRepos_deleteTool(cfg), + tools_repos.CreateRepos_getTool(cfg), + tools_repos.CreateRepos_updateTool(cfg), + tools_codespaces.CreateCodespaces_delete_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_get_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_create_or_update_org_secretTool(cfg), + tools_dependabot.CreateDependabot_list_repo_secretsTool(cfg), + tools_migrations.CreateMigrations_get_status_for_orgTool(cfg), + tools_orgs.CreateOrgs_deleteTool(cfg), + tools_orgs.CreateOrgs_getTool(cfg), + tools_orgs.CreateOrgs_updateTool(cfg), + tools_repos.CreateRepos_delete_fileTool(cfg), + tools_repos.CreateRepos_get_contentTool(cfg), + tools_repos.CreateRepos_create_or_update_file_contentsTool(cfg), + tools_actions.CreateActions_create_registration_token_for_orgTool(cfg), + tools_actions.CreateActions_list_self_hosted_runners_for_orgTool(cfg), + tools_teams.CreateTeams_delete_discussion_comment_legacyTool(cfg), + tools_teams.CreateTeams_get_discussion_comment_legacyTool(cfg), + tools_teams.CreateTeams_update_discussion_comment_legacyTool(cfg), + tools_orgs.CreateOrgs_list_pending_invitationsTool(cfg), + tools_orgs.CreateOrgs_create_invitationTool(cfg), + tools_issues.CreateIssues_list_assigneesTool(cfg), + tools_users.CreateUsers_set_primary_email_visibility_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_delete_repo_rulesetTool(cfg), + tools_repos.CreateRepos_get_repo_rulesetTool(cfg), + tools_repos.CreateRepos_update_repo_rulesetTool(cfg), + tools_repos.CreateRepos_get_repo_ruleset_historyTool(cfg), + tools_billing.CreateBilling_get_github_billing_usage_report_userTool(cfg), + tools_git.CreateGit_get_commitTool(cfg), + tools_emojis.CreateEmojis_getTool(cfg), + tools_activity.CreateActivity_list_public_events_for_userTool(cfg), + tools_apps.CreateApps_get_subscription_plan_for_account_stubbedTool(cfg), + tools_dependabot.CreateDependabot_remove_selected_repo_from_org_secretTool(cfg), + tools_dependabot.CreateDependabot_add_selected_repo_to_org_secretTool(cfg), + tools_repos.CreateRepos_codeowners_errorsTool(cfg), + tools_projects.CreateProjects_list_for_orgTool(cfg), + tools_projects.CreateProjects_create_for_orgTool(cfg), + tools_users.CreateUsers_list_public_emails_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_list_failed_invitationsTool(cfg), + tools_repos.CreateRepos_list_attestationsTool(cfg), + tools_actions.CreateActions_list_repo_variablesTool(cfg), + tools_actions.CreateActions_create_repo_variableTool(cfg), + tools_repos.CreateRepos_list_deployment_statusesTool(cfg), + tools_repos.CreateRepos_create_deployment_statusTool(cfg), + tools_repos.CreateRepos_get_viewsTool(cfg), + tools_reactions.CreateReactions_delete_for_releaseTool(cfg), + tools_dependabot.CreateDependabot_repository_access_for_orgTool(cfg), + tools_dependabot.CreateDependabot_update_repository_access_for_orgTool(cfg), + tools_teams.CreateTeams_list_projects_legacyTool(cfg), + tools_search.CreateSearch_topicsTool(cfg), + tools_users.CreateUsers_unfollowTool(cfg), + tools_users.CreateUsers_check_person_is_followed_by_authenticatedTool(cfg), + tools_users.CreateUsers_followTool(cfg), + tools_projects.CreateProjects_update_columnTool(cfg), + tools_projects.CreateProjects_delete_columnTool(cfg), + tools_projects.CreateProjects_get_columnTool(cfg), + tools_actions.CreateActions_get_actions_cache_usageTool(cfg), + tools_actions.CreateActions_list_jobs_for_workflow_runTool(cfg), + tools_users.CreateUsers_list_attestations_bulkTool(cfg), + tools_teams.CreateTeams_list_discussion_comments_legacyTool(cfg), + tools_teams.CreateTeams_create_discussion_comment_legacyTool(cfg), + tools_repos.CreateRepos_compare_commitsTool(cfg), + tools_codespaces.CreateCodespaces_start_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_delete_deploymentTool(cfg), + tools_repos.CreateRepos_get_deploymentTool(cfg), + tools_reactions.CreateReactions_list_for_releaseTool(cfg), + tools_reactions.CreateReactions_create_for_releaseTool(cfg), + tools_teams.CreateTeams_delete_discussion_comment_in_orgTool(cfg), + tools_teams.CreateTeams_get_discussion_comment_in_orgTool(cfg), + tools_teams.CreateTeams_update_discussion_comment_in_orgTool(cfg), + tools_gists.CreateGists_listTool(cfg), + tools_gists.CreateGists_createTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_alerts_for_orgTool(cfg), + tools_repos.CreateRepos_list_pages_buildsTool(cfg), + tools_repos.CreateRepos_request_pages_buildTool(cfg), + tools_teams.CreateTeams_list_members_in_orgTool(cfg), + tools_interactions.CreateInteractions_remove_restrictions_for_repoTool(cfg), + tools_interactions.CreateInteractions_get_restrictions_for_repoTool(cfg), + tools_interactions.CreateInteractions_set_restrictions_for_repoTool(cfg), + tools_orgs.CreateOrgs_list_for_authenticated_userTool(cfg), + tools_actions.CreateActions_re_run_job_for_workflow_runTool(cfg), + tools_repos.CreateRepos_get_pages_deploymentTool(cfg), + tools_actions.CreateActions_remove_all_custom_labels_from_self_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_list_labels_for_self_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_add_custom_labels_to_self_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_set_custom_labels_for_self_hosted_runner_for_orgTool(cfg), + tools_issues.CreateIssues_check_user_can_be_assignedTool(cfg), + tools_actions.CreateActions_enable_workflowTool(cfg), + tools_teams.CreateTeams_remove_project_legacyTool(cfg), + tools_teams.CreateTeams_check_permissions_for_project_legacyTool(cfg), + tools_teams.CreateTeams_add_or_update_project_permissions_legacyTool(cfg), + tools_actions.CreateActions_create_remove_token_for_repoTool(cfg), + tools_actions.CreateActions_add_repo_access_to_self_hosted_runner_group_in_orgTool(cfg), + tools_actions.CreateActions_remove_repo_access_to_self_hosted_runner_group_in_orgTool(cfg), + tools_git.CreateGit_get_refTool(cfg), + tools_actions.CreateActions_get_custom_oidc_sub_claim_for_repoTool(cfg), + tools_actions.CreateActions_set_custom_oidc_sub_claim_for_repoTool(cfg), + tools_teams.CreateTeams_remove_project_in_orgTool(cfg), + tools_teams.CreateTeams_check_permissions_for_project_in_orgTool(cfg), + tools_teams.CreateTeams_add_or_update_project_permissions_in_orgTool(cfg), + tools_code_scanning.CreateCode_scanning_get_default_setupTool(cfg), + tools_code_scanning.CreateCode_scanning_update_default_setupTool(cfg), + tools_gists.CreateGists_list_commitsTool(cfg), + tools_actions.CreateActions_get_hosted_runners_machine_specs_for_orgTool(cfg), + tools_oidc.CreateOidc_update_oidc_custom_sub_template_for_orgTool(cfg), + tools_oidc.CreateOidc_get_oidc_custom_sub_template_for_orgTool(cfg), + tools_packages.CreatePackages_list_docker_migration_conflicting_packages_for_organizationTool(cfg), + tools_issues.CreateIssues_reprioritize_sub_issueTool(cfg), + tools_issues.CreateIssues_list_eventsTool(cfg), + tools_repos.CreateRepos_get_pages_health_checkTool(cfg), + tools_activity.CreateActivity_list_repo_eventsTool(cfg), + tools_packages.CreatePackages_list_packages_for_authenticated_userTool(cfg), + tools_billing.CreateBilling_get_shared_storage_billing_orgTool(cfg), + tools_repos.CreateRepos_delete_tag_protectionTool(cfg), + tools_repos.CreateRepos_list_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_create_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_stop_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_repo_machines_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_repo_organization_variablesTool(cfg), + tools_checks.CreateChecks_list_suites_for_refTool(cfg), + tools_actions.CreateActions_list_runner_applications_for_repoTool(cfg), + tools_dependency_graph.CreateDependency_graph_export_sbomTool(cfg), + tools_teams.CreateTeams_list_pending_invitations_legacyTool(cfg), + tools_actions.CreateActions_delete_repo_variableTool(cfg), + tools_actions.CreateActions_get_repo_variableTool(cfg), + tools_actions.CreateActions_update_repo_variableTool(cfg), + tools_hosted_compute.CreateHosted_compute_list_network_configurations_for_orgTool(cfg), + tools_hosted_compute.CreateHosted_compute_create_network_configuration_for_orgTool(cfg), + tools_repos.CreateRepos_disable_deployment_protection_ruleTool(cfg), + tools_repos.CreateRepos_get_custom_deployment_protection_ruleTool(cfg), + tools_actions.CreateActions_delete_environment_variableTool(cfg), + tools_actions.CreateActions_get_environment_variableTool(cfg), + tools_actions.CreateActions_update_environment_variableTool(cfg), + tools_reactions.CreateReactions_list_for_pull_request_review_commentTool(cfg), + tools_reactions.CreateReactions_create_for_pull_request_review_commentTool(cfg), + tools_orgs.CreateOrgs_update_membership_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_get_membership_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_get_feedsTool(cfg), + tools_activity.CreateActivity_list_repos_starred_by_authenticated_userTool(cfg), + tools_classroom.CreateClassroom_list_classroomsTool(cfg), + tools_git.CreateGit_get_treeTool(cfg), + tools_repos.CreateRepos_get_webhook_config_for_repoTool(cfg), + tools_repos.CreateRepos_update_webhook_config_for_repoTool(cfg), + tools_git.CreateGit_get_blobTool(cfg), + tools_code_security.CreateCode_security_attach_configurationTool(cfg), + tools_packages.CreatePackages_get_package_for_organizationTool(cfg), + tools_packages.CreatePackages_delete_package_for_orgTool(cfg), + tools_packages.CreatePackages_get_package_for_userTool(cfg), + tools_packages.CreatePackages_delete_package_for_userTool(cfg), + tools_classroom.CreateClassroom_get_a_classroomTool(cfg), + tools_orgs.CreateOrgs_list_outside_collaboratorsTool(cfg), + tools_repos.CreateRepos_decline_invitation_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_accept_invitation_for_authenticated_userTool(cfg), + tools_apps.CreateApps_get_user_installationTool(cfg), + tools_actions.CreateActions_generate_runner_jitconfig_for_orgTool(cfg), + tools_teams.CreateTeams_remove_membership_for_user_legacyTool(cfg), + tools_teams.CreateTeams_get_membership_for_user_legacyTool(cfg), + tools_teams.CreateTeams_add_or_update_membership_for_user_legacyTool(cfg), + tools_reactions.CreateReactions_create_for_commit_commentTool(cfg), + tools_reactions.CreateReactions_list_for_commit_commentTool(cfg), + tools_packages.CreatePackages_list_packages_for_userTool(cfg), + tools_repos.CreateRepos_get_org_rule_suiteTool(cfg), + tools_apps.CreateApps_delete_tokenTool(cfg), + tools_apps.CreateApps_reset_tokenTool(cfg), + tools_apps.CreateApps_check_tokenTool(cfg), + tools_orgs.CreateApi_insights_get_user_statsTool(cfg), + tools_orgs.CreateOrgs_get_org_roleTool(cfg), + tools_repos.CreateRepos_create_pages_deploymentTool(cfg), + tools_apps.CreateApps_scope_tokenTool(cfg), + tools_activity.CreateActivity_list_repos_watched_by_userTool(cfg), + tools_actions.CreateActions_get_actions_cache_usage_by_repo_for_orgTool(cfg), + tools_migrations.CreateMigrations_map_commit_authorTool(cfg), + tools_billing.CreateBilling_get_github_actions_billing_orgTool(cfg), + tools_teams.CreateTeams_list_discussion_comments_in_orgTool(cfg), + tools_teams.CreateTeams_create_discussion_comment_in_orgTool(cfg), + tools_users.CreateUsers_check_following_for_userTool(cfg), + tools_apps.CreateApps_list_subscriptions_for_authenticated_userTool(cfg), + tools_migrations.CreateMigrations_unlock_repo_for_orgTool(cfg), + tools_codes_of_conduct.CreateCodes_of_conduct_get_all_codes_of_conductTool(cfg), + tools_actions.CreateActions_remove_all_custom_labels_from_self_hosted_runner_for_repoTool(cfg), + tools_actions.CreateActions_list_labels_for_self_hosted_runner_for_repoTool(cfg), + tools_actions.CreateActions_add_custom_labels_to_self_hosted_runner_for_repoTool(cfg), + tools_actions.CreateActions_set_custom_labels_for_self_hosted_runner_for_repoTool(cfg), + tools_dependabot.CreateDependabot_get_org_public_keyTool(cfg), + tools_users.CreateUsers_list_public_keys_for_userTool(cfg), + tools_activity.CreateActivity_list_org_events_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_get_autolinkTool(cfg), + tools_repos.CreateRepos_delete_autolinkTool(cfg), + tools_gists.CreateGists_delete_commentTool(cfg), + tools_gists.CreateGists_get_commentTool(cfg), + tools_gists.CreateGists_update_commentTool(cfg), + tools_issues.CreateIssues_remove_sub_issueTool(cfg), + tools_code_security.CreateCode_security_get_configurations_for_enterpriseTool(cfg), + tools_code_security.CreateCode_security_create_configuration_for_enterpriseTool(cfg), + tools_gists.CreateGists_list_starredTool(cfg), + tools_orgs.CreateOrgs_delete_webhookTool(cfg), + tools_orgs.CreateOrgs_get_webhookTool(cfg), + tools_orgs.CreateOrgs_update_webhookTool(cfg), + tools_repos.CreateRepos_list_autolinksTool(cfg), + tools_repos.CreateRepos_create_autolinkTool(cfg), + tools_orgs.CreateApi_insights_get_summary_statsTool(cfg), + tools_actions.CreateActions_remove_custom_label_from_self_hosted_runner_for_orgTool(cfg), + tools_code_security.CreateCode_security_get_configuration_for_repositoryTool(cfg), + tools_actions.CreateActions_cancel_workflow_runTool(cfg), + tools_orgs.CreateOrgs_list_pat_grant_request_repositoriesTool(cfg), + tools_actions.CreateActions_get_github_actions_default_workflow_permissions_repositoryTool(cfg), + tools_actions.CreateActions_set_github_actions_default_workflow_permissions_repositoryTool(cfg), + tools_repos.CreateRepos_get_branch_rulesTool(cfg), + tools_users.CreateUsers_list_followed_by_authenticated_userTool(cfg), + tools_actions.CreateActions_list_environment_secretsTool(cfg), + tools_repos.CreateRepos_list_commitsTool(cfg), + tools_orgs.CreateOrgs_list_memberships_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_list_invitation_teamsTool(cfg), + tools_campaigns.CreateCampaigns_delete_campaignTool(cfg), + tools_campaigns.CreateCampaigns_get_campaign_summaryTool(cfg), + tools_campaigns.CreateCampaigns_update_campaignTool(cfg), + tools_orgs.CreateApi_insights_get_time_statsTool(cfg), + tools_codespaces.CreateCodespaces_list_repositories_for_secret_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_set_repositories_for_secret_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_delete_attestations_bulkTool(cfg), + tools_orgs.CreateOrgs_remove_membership_for_userTool(cfg), + tools_orgs.CreateOrgs_get_membership_for_userTool(cfg), + tools_orgs.CreateOrgs_set_membership_for_userTool(cfg), + tools_codespaces.CreateCodespaces_stop_in_organizationTool(cfg), + tools_pulls.CreatePulls_delete_pending_reviewTool(cfg), + tools_pulls.CreatePulls_get_reviewTool(cfg), + tools_pulls.CreatePulls_update_reviewTool(cfg), + tools_classroom.CreateClassroom_list_accepted_assignments_for_an_assignmentTool(cfg), + tools_activity.CreateActivity_list_notifications_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_mark_notifications_as_readTool(cfg), + tools_copilot.CreateCopilot_get_copilot_organization_detailsTool(cfg), + tools_actions.CreateActions_get_workflow_usageTool(cfg), + tools_codespaces.CreateCodespaces_delete_from_organizationTool(cfg), + tools_orgs.CreateOrgs_ping_webhookTool(cfg), + tools_packages.CreatePackages_restore_package_version_for_userTool(cfg), + tools_orgs.CreateOrgs_list_blocked_usersTool(cfg), + tools_codespaces.CreateCodespaces_list_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_create_for_authenticated_userTool(cfg), + tools_users.CreateUsers_unblockTool(cfg), + tools_users.CreateUsers_check_blockedTool(cfg), + tools_users.CreateUsers_blockTool(cfg), + tools_search.CreateSearch_usersTool(cfg), + tools_code_scanning.CreateCode_scanning_upload_sarifTool(cfg), + tools_issues.CreateIssues_remove_all_labelsTool(cfg), + tools_issues.CreateIssues_list_labels_on_issueTool(cfg), + tools_issues.CreateIssues_add_labelsTool(cfg), + tools_issues.CreateIssues_set_labelsTool(cfg), + tools_repos.CreateRepos_list_comments_for_commitTool(cfg), + tools_repos.CreateRepos_create_commit_commentTool(cfg), + tools_classroom.CreateClassroom_list_assignments_for_a_classroomTool(cfg), + tools_code_scanning.CreateCode_scanning_delete_analysisTool(cfg), + tools_code_scanning.CreateCode_scanning_get_analysisTool(cfg), + tools_activity.CreateActivity_list_public_events_for_repo_networkTool(cfg), + tools_issues.CreateIssues_list_commentsTool(cfg), + tools_issues.CreateIssues_create_commentTool(cfg), + tools_actions.CreateActions_delete_repo_secretTool(cfg), + tools_actions.CreateActions_get_repo_secretTool(cfg), + tools_actions.CreateActions_create_or_update_repo_secretTool(cfg), + tools_repos.CreateRepos_transferTool(cfg), + tools_orgs.CreateOrgs_get_webhook_config_for_orgTool(cfg), + tools_orgs.CreateOrgs_update_webhook_config_for_orgTool(cfg), + tools_repos.CreateRepos_get_all_topicsTool(cfg), + tools_repos.CreateRepos_replace_all_topicsTool(cfg), + tools_code_security.CreateCode_security_get_single_configuration_for_enterpriseTool(cfg), + tools_code_security.CreateCode_security_update_enterprise_configurationTool(cfg), + tools_code_security.CreateCode_security_delete_configuration_for_enterpriseTool(cfg), + tools_migrations.CreateMigrations_get_commit_authorsTool(cfg), + tools_git.CreateGit_create_refTool(cfg), + tools_billing.CreateBilling_get_shared_storage_billing_userTool(cfg), + tools_users.CreateUsers_list_gpg_keys_for_userTool(cfg), + tools_repos.CreateRepos_get_repo_rule_suitesTool(cfg), + tools_actions.CreateActions_remove_custom_label_from_self_hosted_runner_for_repoTool(cfg), + tools_licenses.CreateLicenses_get_for_repoTool(cfg), + tools_actions.CreateActions_get_hosted_runners_limits_for_orgTool(cfg), + tools_repos.CreateRepos_list_contributorsTool(cfg), + tools_users.CreateUsers_delete_attestations_by_subject_digestTool(cfg), + tools_projects.CreateProjects_create_for_authenticated_userTool(cfg), + tools_actions.CreateActions_get_allowed_actions_organizationTool(cfg), + tools_actions.CreateActions_set_allowed_actions_organizationTool(cfg), + tools_actions.CreateActions_list_selected_repos_for_org_variableTool(cfg), + tools_actions.CreateActions_set_selected_repos_for_org_variableTool(cfg), + tools_repos.CreateRepos_list_for_userTool(cfg), + tools_repos.CreateRepos_get_repo_rule_suiteTool(cfg), + tools_actions.CreateActions_list_self_hosted_runners_in_group_for_orgTool(cfg), + tools_actions.CreateActions_set_self_hosted_runners_in_group_for_orgTool(cfg), + tools_copilot.CreateCopilot_list_copilot_seatsTool(cfg), + tools_actions.CreateActions_list_repo_organization_secretsTool(cfg), + tools_repos.CreateRepos_delete_admin_branch_protectionTool(cfg), + tools_repos.CreateRepos_get_admin_branch_protectionTool(cfg), + tools_repos.CreateRepos_set_admin_branch_protectionTool(cfg), + tools_meta.CreateMeta_get_zenTool(cfg), + tools_actions.CreateActions_list_workflow_runs_for_repoTool(cfg), + tools_codespaces.CreateCodespaces_pre_flight_with_repo_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_delete_releaseTool(cfg), + tools_repos.CreateRepos_get_releaseTool(cfg), + tools_repos.CreateRepos_update_releaseTool(cfg), + tools_apps.CreateApps_list_installationsTool(cfg), + tools_repos.CreateRepos_delete_commit_signature_protectionTool(cfg), + tools_repos.CreateRepos_get_commit_signature_protectionTool(cfg), + tools_repos.CreateRepos_create_commit_signature_protectionTool(cfg), + tools_meta.CreateMeta_getTool(cfg), + tools_codespaces.CreateCodespaces_codespace_machines_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_remove_memberTool(cfg), + tools_orgs.CreateOrgs_check_membership_for_userTool(cfg), + tools_repos.CreateRepos_download_zipball_archiveTool(cfg), + tools_security_advisories.CreateSecurity_advisories_list_org_repository_advisoriesTool(cfg), + tools_activity.CreateActivity_list_public_eventsTool(cfg), + tools_actions.CreateActions_delete_org_secretTool(cfg), + tools_actions.CreateActions_get_org_secretTool(cfg), + tools_actions.CreateActions_create_or_update_org_secretTool(cfg), + tools_issues.CreateIssues_getTool(cfg), + tools_issues.CreateIssues_updateTool(cfg), + tools_apps.CreateApps_delete_authorizationTool(cfg), + tools_users.CreateUsers_list_blocked_by_authenticated_userTool(cfg), + tools_licenses.CreateLicenses_get_all_commonly_usedTool(cfg), + tools_projects.CreateProjects_get_permission_for_userTool(cfg), + tools_interactions.CreateInteractions_remove_restrictions_for_orgTool(cfg), + tools_interactions.CreateInteractions_get_restrictions_for_orgTool(cfg), + tools_interactions.CreateInteractions_set_restrictions_for_orgTool(cfg), + tools_actions.CreateActions_create_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_list_hosted_runners_for_orgTool(cfg), + tools_reactions.CreateReactions_list_for_issueTool(cfg), + tools_reactions.CreateReactions_create_for_issueTool(cfg), + tools_code_scanning.CreateCode_scanning_list_alerts_for_orgTool(cfg), + tools_repos.CreateRepos_get_users_with_access_to_protected_branchTool(cfg), + tools_repos.CreateRepos_add_user_access_restrictionsTool(cfg), + tools_repos.CreateRepos_set_user_access_restrictionsTool(cfg), + tools_repos.CreateRepos_remove_user_access_restrictionsTool(cfg), + tools_repos.CreateRepos_list_teamsTool(cfg), + tools_repos.CreateRepos_disable_automated_security_fixesTool(cfg), + tools_repos.CreateRepos_check_automated_security_fixesTool(cfg), + tools_repos.CreateRepos_enable_automated_security_fixesTool(cfg), + tools_issues.CreateIssues_delete_labelTool(cfg), + tools_issues.CreateIssues_get_labelTool(cfg), + tools_issues.CreateIssues_update_labelTool(cfg), + tools_orgs.CreateOrgs_get_webhook_deliveryTool(cfg), + tools_checks.CreateChecks_list_for_refTool(cfg), + tools_orgs.CreateOrgs_list_app_installationsTool(cfg), + tools_actions.CreateActions_remove_selected_repo_from_org_secretTool(cfg), + tools_actions.CreateActions_add_selected_repo_to_org_secretTool(cfg), + tools_orgs.CreateOrgs_list_attestationsTool(cfg), + tools_code_security.CreateCode_security_delete_configurationTool(cfg), + tools_code_security.CreateCode_security_get_configurationTool(cfg), + tools_code_security.CreateCode_security_update_configurationTool(cfg), + tools_git.CreateGit_create_tagTool(cfg), + tools_code_scanning.CreateCode_scanning_get_variant_analysis_repo_taskTool(cfg), + tools_copilot.CreateCopilot_get_copilot_seat_details_for_userTool(cfg), + tools_issues.CreateIssues_delete_milestoneTool(cfg), + tools_issues.CreateIssues_get_milestoneTool(cfg), + tools_issues.CreateIssues_update_milestoneTool(cfg), + tools_repos.CreateRepos_update_invitationTool(cfg), + tools_repos.CreateRepos_delete_invitationTool(cfg), + tools_codespaces.CreateCodespaces_list_devcontainers_in_repository_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_get_public_key_for_authenticated_userTool(cfg), + tools_teams.CreateTeams_delete_in_orgTool(cfg), + tools_teams.CreateTeams_get_by_nameTool(cfg), + tools_teams.CreateTeams_update_in_orgTool(cfg), + tools_repos.CreateRepos_list_release_assetsTool(cfg), + tools_orgs.CreateOrgs_list_org_role_usersTool(cfg), + tools_hosted_compute.CreateHosted_compute_get_network_settings_for_orgTool(cfg), + tools_repos.CreateRepos_set_status_check_contextsTool(cfg), + tools_repos.CreateRepos_remove_status_check_contextsTool(cfg), + tools_repos.CreateRepos_get_all_status_check_contextsTool(cfg), + tools_repos.CreateRepos_add_status_check_contextsTool(cfg), + tools_actions.CreateActions_create_workflow_dispatchTool(cfg), + tools_pulls.CreatePulls_getTool(cfg), + tools_pulls.CreatePulls_updateTool(cfg), + tools_repos.CreateRepos_list_for_orgTool(cfg), + tools_repos.CreateRepos_create_in_orgTool(cfg), + tools_orgs.CreateOrgs_list_webhook_deliveriesTool(cfg), + tools_teams.CreateTeams_list_child_legacyTool(cfg), + tools_projects.CreateProjects_delete_cardTool(cfg), + tools_projects.CreateProjects_get_cardTool(cfg), + tools_projects.CreateProjects_update_cardTool(cfg), + tools_private_registries.CreatePrivate_registries_get_org_public_keyTool(cfg), + tools_code_security.CreateCode_security_set_configuration_as_defaultTool(cfg), + tools_packages.CreatePackages_list_packages_for_organizationTool(cfg), + tools_apps.CreateApps_get_org_installationTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_private_vulnerability_reportTool(cfg), + tools_actions.CreateActions_get_workflowTool(cfg), + tools_repos.CreateRepos_get_all_environmentsTool(cfg), + tools_gists.CreateGists_getTool(cfg), + tools_gists.CreateGists_updateTool(cfg), + tools_gists.CreateGists_deleteTool(cfg), + tools_apps.CreateApps_list_webhook_deliveriesTool(cfg), + tools_code_scanning.CreateCode_scanning_get_variant_analysisTool(cfg), + tools_codespaces.CreateCodespaces_list_repo_secretsTool(cfg), + tools_orgs.CreateOrgs_create_webhookTool(cfg), + tools_orgs.CreateOrgs_list_webhooksTool(cfg), + tools_dependabot.CreateDependabot_delete_org_secretTool(cfg), + tools_dependabot.CreateDependabot_get_org_secretTool(cfg), + tools_dependabot.CreateDependabot_create_or_update_org_secretTool(cfg), + tools_repos.CreateRepos_delete_webhookTool(cfg), + tools_repos.CreateRepos_get_webhookTool(cfg), + tools_repos.CreateRepos_update_webhookTool(cfg), + tools_actions.CreateActions_get_allowed_actions_repositoryTool(cfg), + tools_actions.CreateActions_set_allowed_actions_repositoryTool(cfg), + tools_orgs.CreateOrgs_list_pat_grant_repositoriesTool(cfg), + tools_actions.CreateActions_list_github_hosted_runners_in_group_for_orgTool(cfg), + tools_issues.CreateIssues_lockTool(cfg), + tools_issues.CreateIssues_unlockTool(cfg), + tools_code_security.CreateCode_security_get_default_configurationsTool(cfg), + tools_actions.CreateActions_delete_self_hosted_runner_from_orgTool(cfg), + tools_actions.CreateActions_get_self_hosted_runner_for_orgTool(cfg), + tools_search.CreateSearch_commitsTool(cfg), + tools_repos.CreateRepos_check_collaboratorTool(cfg), + tools_repos.CreateRepos_add_collaboratorTool(cfg), + tools_repos.CreateRepos_remove_collaboratorTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_repository_advisory_cve_requestTool(cfg), + tools_repos.CreateRepos_get_top_pathsTool(cfg), + tools_secret_scanning.CreateSecret_scanning_get_scan_historyTool(cfg), + tools_repos.CreateRepos_get_all_deployment_protection_rulesTool(cfg), + tools_repos.CreateRepos_create_deployment_protection_ruleTool(cfg), + tools_actions.CreateActions_force_cancel_workflow_runTool(cfg), + tools_projects.CreateProjects_list_for_userTool(cfg), + tools_migrations.CreateMigrations_start_for_authenticated_userTool(cfg), + tools_migrations.CreateMigrations_list_for_authenticated_userTool(cfg), + tools_classroom.CreateClassroom_get_an_assignmentTool(cfg), + tools_apps.CreateApps_list_installation_repos_for_authenticated_userTool(cfg), + tools_migrations.CreateMigrations_set_lfs_preferenceTool(cfg), + tools_orgs.CreateApi_insights_get_time_stats_by_userTool(cfg), + tools_orgs.CreateApi_insights_get_route_stats_by_actorTool(cfg), + tools_actions.CreateActions_list_repo_secretsTool(cfg), + tools_checks.CreateChecks_rerequest_suiteTool(cfg), + tools_pulls.CreatePulls_create_reply_for_review_commentTool(cfg), + tools_users.CreateUsers_delete_social_account_for_authenticated_userTool(cfg), + tools_users.CreateUsers_list_social_accounts_for_authenticated_userTool(cfg), + tools_users.CreateUsers_add_social_account_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_branchesTool(cfg), + tools_copilot.CreateCopilot_copilot_metrics_for_organizationTool(cfg), + tools_orgs.CreateOrgs_list_pat_grant_requestsTool(cfg), + tools_orgs.CreateOrgs_review_pat_grant_requests_in_bulkTool(cfg), + tools_codespaces.CreateCodespaces_list_selected_repos_for_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_set_selected_repos_for_org_secretTool(cfg), + tools_users.CreateUsers_delete_gpg_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_get_gpg_key_for_authenticated_userTool(cfg), + tools_actions.CreateActions_create_registration_token_for_repoTool(cfg), + tools_actions.CreateActions_get_workflow_run_usageTool(cfg), + tools_repos.CreateRepos_list_releasesTool(cfg), + tools_repos.CreateRepos_create_releaseTool(cfg), + tools_repos.CreateRepos_get_webhook_deliveryTool(cfg), + tools_codespaces.CreateCodespaces_get_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_update_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_delete_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_list_in_repository_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_create_with_repo_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_create_attestationTool(cfg), + tools_codespaces.CreateCodespaces_list_in_organizationTool(cfg), + tools_issues.CreateIssues_get_eventTool(cfg), + tools_interactions.CreateInteractions_remove_restrictions_for_authenticated_userTool(cfg), + tools_interactions.CreateInteractions_get_restrictions_for_authenticated_userTool(cfg), + tools_interactions.CreateInteractions_set_restrictions_for_authenticated_userTool(cfg), + tools_codes_of_conduct.CreateCodes_of_conduct_get_conduct_codeTool(cfg), + tools_reactions.CreateReactions_delete_for_commit_commentTool(cfg), + tools_actions.CreateActions_get_hosted_runners_platforms_for_orgTool(cfg), + tools_search.CreateSearch_issues_and_pull_requestsTool(cfg), + tools_repos.CreateRepos_get_branchTool(cfg), + tools_projects.CreateProjects_list_cardsTool(cfg), + tools_projects.CreateProjects_create_cardTool(cfg), + tools_dependency_graph.CreateDependency_graph_create_repository_snapshotTool(cfg), + tools_packages.CreatePackages_restore_package_version_for_orgTool(cfg), + tools_actions.CreateActions_get_github_actions_permissions_organizationTool(cfg), + tools_actions.CreateActions_set_github_actions_permissions_organizationTool(cfg), + tools_users.CreateUsers_delete_attestations_bulkTool(cfg), + tools_apps.CreateApps_remove_repo_from_installation_for_authenticated_userTool(cfg), + tools_apps.CreateApps_add_repo_to_installation_for_authenticated_userTool(cfg), + tools_code_scanning.CreateCode_scanning_list_recent_analysesTool(cfg), + tools_teams.CreateTeams_list_discussions_in_orgTool(cfg), + tools_teams.CreateTeams_create_discussion_in_orgTool(cfg), + tools_users.CreateUsers_listTool(cfg), + tools_repos.CreateRepos_get_readme_in_directoryTool(cfg), + tools_orgs.CreateApi_insights_get_subject_statsTool(cfg), + tools_repos.CreateRepos_get_pages_buildTool(cfg), + tools_repos.CreateRepos_get_contributors_statsTool(cfg), + tools_code_security.CreateCode_security_detach_configurationTool(cfg), + tools_billing.CreateBilling_get_github_billing_usage_report_orgTool(cfg), + tools_repos.CreateRepos_get_latest_pages_buildTool(cfg), + tools_packages.CreatePackages_get_package_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_delete_package_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_list_org_role_teamsTool(cfg), + tools_repos.CreateRepos_update_pull_request_review_protectionTool(cfg), + tools_repos.CreateRepos_delete_pull_request_review_protectionTool(cfg), + tools_repos.CreateRepos_get_pull_request_review_protectionTool(cfg), + tools_repos.CreateRepos_list_branches_for_head_commitTool(cfg), + tools_code_security.CreateCode_security_get_repositories_for_configurationTool(cfg), + tools_repos.CreateRepos_get_release_by_tagTool(cfg), + tools_reactions.CreateReactions_delete_for_issueTool(cfg), + tools_gists.CreateGists_unstarTool(cfg), + tools_gists.CreateGists_check_is_starredTool(cfg), + tools_gists.CreateGists_starTool(cfg), + tools_actions.CreateActions_delete_org_variableTool(cfg), + tools_actions.CreateActions_get_org_variableTool(cfg), + tools_actions.CreateActions_update_org_variableTool(cfg), + tools_repos.CreateRepos_list_invitations_for_authenticated_userTool(cfg), + tools_apps.CreateApps_create_installation_access_tokenTool(cfg), + tools_campaigns.CreateCampaigns_list_org_campaignsTool(cfg), + tools_campaigns.CreateCampaigns_create_campaignTool(cfg), + tools_repos.CreateRepos_mergeTool(cfg), + tools_projects.CreateProjects_move_columnTool(cfg), + tools_search.CreateSearch_labelsTool(cfg), + tools_orgs.CreateOrgs_list_issue_typesTool(cfg), + tools_orgs.CreateOrgs_create_issue_typeTool(cfg), + tools_actions.CreateActions_delete_actions_cache_by_keyTool(cfg), + tools_actions.CreateActions_get_actions_cache_listTool(cfg), + tools_orgs.CreateOrgs_list_membersTool(cfg), + tools_repos.CreateRepos_delete_deploy_keyTool(cfg), + tools_repos.CreateRepos_get_deploy_keyTool(cfg), + tools_pulls.CreatePulls_list_review_comments_for_repoTool(cfg), + tools_orgs.CreateApi_insights_get_summary_stats_by_userTool(cfg), + tools_checks.CreateChecks_list_annotationsTool(cfg), + tools_actions.CreateActions_delete_self_hosted_runner_from_repoTool(cfg), + tools_actions.CreateActions_get_self_hosted_runner_for_repoTool(cfg), + tools_actions.CreateActions_list_self_hosted_runners_for_repoTool(cfg), + tools_actions.CreateActions_review_custom_gates_for_runTool(cfg), + tools_secret_scanning.CreateSecret_scanning_update_alertTool(cfg), + tools_secret_scanning.CreateSecret_scanning_get_alertTool(cfg), + tools_actions.CreateActions_set_github_actions_default_workflow_permissions_organizationTool(cfg), + tools_actions.CreateActions_get_github_actions_default_workflow_permissions_organizationTool(cfg), + tools_repos.CreateRepos_list_commit_statuses_for_refTool(cfg), + tools_pulls.CreatePulls_remove_requested_reviewersTool(cfg), + tools_pulls.CreatePulls_list_requested_reviewersTool(cfg), + tools_pulls.CreatePulls_request_reviewersTool(cfg), + tools_orgs.CreateOrgs_revoke_all_org_roles_userTool(cfg), + tools_repos.CreateRepos_merge_upstreamTool(cfg), + tools_users.CreateUsers_list_ssh_signing_keys_for_userTool(cfg), + tools_licenses.CreateLicenses_getTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_comment_in_orgTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_comment_in_orgTool(cfg), + tools_migrations.CreateMigrations_delete_archive_for_orgTool(cfg), + tools_migrations.CreateMigrations_download_archive_for_orgTool(cfg), + tools_gists.CreateGists_get_revisionTool(cfg), + tools_users.CreateUsers_list_followers_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_commit_comments_for_repoTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_in_orgTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_in_orgTool(cfg), + tools_apps.CreateApps_list_subscriptions_for_authenticated_user_stubbedTool(cfg), + tools_actions.CreateActions_get_github_actions_permissions_repositoryTool(cfg), + tools_actions.CreateActions_set_github_actions_permissions_repositoryTool(cfg), + tools_teams.CreateTeams_add_or_update_repo_permissions_in_orgTool(cfg), + tools_teams.CreateTeams_remove_repo_in_orgTool(cfg), + tools_teams.CreateTeams_check_permissions_for_repo_in_orgTool(cfg), + tools_repos.CreateRepos_remove_team_access_restrictionsTool(cfg), + tools_repos.CreateRepos_get_teams_with_access_to_protected_branchTool(cfg), + tools_repos.CreateRepos_add_team_access_restrictionsTool(cfg), + tools_repos.CreateRepos_set_team_access_restrictionsTool(cfg), + tools_activity.CreateActivity_list_repos_starred_by_userTool(cfg), + tools_copilot.CreateCopilot_cancel_copilot_seat_assignment_for_teamsTool(cfg), + tools_copilot.CreateCopilot_add_copilot_seats_for_teamsTool(cfg), + tools_users.CreateUsers_list_following_for_userTool(cfg), + tools_orgs.CreateOrgs_redeliver_webhook_deliveryTool(cfg), + tools_users.CreateUsers_list_public_ssh_keys_for_authenticated_userTool(cfg), + tools_users.CreateUsers_create_public_ssh_key_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_artifacts_for_repoTool(cfg), + tools_orgs.CreateOrgs_list_public_membersTool(cfg), + tools_orgs.CreateOrgs_review_pat_grant_requestTool(cfg), + tools_apps.CreateApps_list_plansTool(cfg), + tools_teams.CreateTeams_delete_legacyTool(cfg), + tools_teams.CreateTeams_get_legacyTool(cfg), + tools_teams.CreateTeams_update_legacyTool(cfg), + tools_migrations.CreateMigrations_list_repos_for_orgTool(cfg), + tools_checks.CreateChecks_create_suiteTool(cfg), + tools_actions.CreateActions_get_pending_deployments_for_runTool(cfg), + tools_actions.CreateActions_review_pending_deployments_for_runTool(cfg), + tools_teams.CreateTeams_list_repos_legacyTool(cfg), + tools_actions.CreateActions_remove_selected_repo_from_org_variableTool(cfg), + tools_actions.CreateActions_add_selected_repo_to_org_variableTool(cfg), + tools_activity.CreateActivity_check_repo_is_starred_by_authenticated_userTool(cfg), + tools_activity.CreateActivity_star_repo_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_unstar_repo_for_authenticated_userTool(cfg), + tools_actions.CreateActions_get_org_public_keyTool(cfg), + tools_actions.CreateActions_get_hosted_runners_github_owned_images_for_orgTool(cfg), + tools_issues.CreateIssues_add_sub_issueTool(cfg), + tools_issues.CreateIssues_list_sub_issuesTool(cfg), + tools_meta.CreateMeta_get_all_versionsTool(cfg), + tools_repos.CreateRepos_get_top_referrersTool(cfg), + tools_issues.CreateIssues_list_for_authenticated_userTool(cfg), + tools_actions.CreateActions_get_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_update_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_delete_hosted_runner_for_orgTool(cfg), + tools_activity.CreateActivity_list_events_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_delete_thread_subscriptionTool(cfg), + tools_activity.CreateActivity_get_thread_subscription_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_set_thread_subscriptionTool(cfg), + tools_repos.CreateRepos_delete_access_restrictionsTool(cfg), + tools_repos.CreateRepos_get_access_restrictionsTool(cfg), + tools_apps.CreateApps_get_subscription_plan_for_accountTool(cfg), + tools_repos.CreateRepos_update_release_assetTool(cfg), + tools_repos.CreateRepos_delete_release_assetTool(cfg), + tools_repos.CreateRepos_get_release_assetTool(cfg), + tools_gists.CreateGists_list_publicTool(cfg), + tools_orgs.CreateOrgs_delete_attestations_by_idTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_alerts_for_enterpriseTool(cfg), + tools_packages.CreatePackages_delete_package_version_for_orgTool(cfg), + tools_packages.CreatePackages_get_package_version_for_organizationTool(cfg), + tools_teams.CreateTeams_list_repos_in_orgTool(cfg), + tools_users.CreateUsers_delete_attestations_by_idTool(cfg), + tools_pulls.CreatePulls_dismiss_reviewTool(cfg), + tools_teams.CreateTeams_listTool(cfg), + tools_teams.CreateTeams_createTool(cfg), + tools_packages.CreatePackages_restore_package_for_userTool(cfg), + tools_repos.CreateRepos_list_webhooksTool(cfg), + tools_repos.CreateRepos_create_webhookTool(cfg), + tools_orgs.CreateOrgs_remove_outside_collaboratorTool(cfg), + tools_orgs.CreateOrgs_convert_member_to_outside_collaboratorTool(cfg), + tools_users.CreateUsers_list_social_accounts_for_userTool(cfg), + tools_reactions.CreateReactions_delete_for_team_discussionTool(cfg), + tools_repos.CreateRepos_enable_private_vulnerability_reportingTool(cfg), + tools_repos.CreateRepos_disable_private_vulnerability_reportingTool(cfg), + tools_repos.CreateRepos_check_private_vulnerability_reportingTool(cfg), + tools_repos.CreateRepos_rename_branchTool(cfg), + tools_actions.CreateActions_list_selected_repos_for_org_secretTool(cfg), + tools_actions.CreateActions_set_selected_repos_for_org_secretTool(cfg), + tools_code_scanning.CreateCode_scanning_list_alerts_for_repoTool(cfg), + tools_repos.CreateRepos_list_collaboratorsTool(cfg), + tools_apps.CreateApps_get_authenticatedTool(cfg), + tools_pulls.CreatePulls_list_commitsTool(cfg), + tools_apps.CreateApps_list_plans_stubbedTool(cfg), + tools_activity.CreateActivity_mark_thread_as_doneTool(cfg), + tools_activity.CreateActivity_get_threadTool(cfg), + tools_activity.CreateActivity_mark_thread_as_readTool(cfg), + tools_gists.CreateGists_list_forksTool(cfg), + tools_gists.CreateGists_forkTool(cfg), + tools_orgs.CreateOrgs_list_org_rolesTool(cfg), + tools_apps.CreateApps_list_installation_requests_for_authenticated_appTool(cfg), + tools_packages.CreatePackages_list_docker_migration_conflicting_packages_for_authenticated_userTool(cfg), + tools_projects.CreateProjects_list_for_repoTool(cfg), + tools_projects.CreateProjects_create_for_repoTool(cfg), + tools_repos.CreateRepos_get_deployment_statusTool(cfg), + tools_migrations.CreateMigrations_list_for_orgTool(cfg), + tools_migrations.CreateMigrations_start_for_orgTool(cfg), + tools_dependabot.CreateDependabot_delete_repo_secretTool(cfg), + tools_dependabot.CreateDependabot_get_repo_secretTool(cfg), + tools_dependabot.CreateDependabot_create_or_update_repo_secretTool(cfg), + tools_repos.CreateRepos_list_tag_protectionTool(cfg), + tools_repos.CreateRepos_create_tag_protectionTool(cfg), + tools_code_security.CreateCode_security_attach_enterprise_configurationTool(cfg), + tools_apps.CreateApps_redeliver_webhook_deliveryTool(cfg), + tools_dependabot.CreateDependabot_get_repo_public_keyTool(cfg), + tools_repos.CreateRepos_get_combined_status_for_refTool(cfg), + tools_actions.CreateActions_get_repo_public_keyTool(cfg), + tools_codespaces.CreateCodespaces_get_org_public_keyTool(cfg), + tools_code_security.CreateCode_security_set_configuration_as_default_for_enterpriseTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_forkTool(cfg), + tools_code_security.CreateCode_security_get_default_configurations_for_enterpriseTool(cfg), + tools_apps.CreateApps_list_accounts_for_planTool(cfg), + tools_orgs.CreateOrgs_list_security_manager_teamsTool(cfg), + tools_teams.CreateTeams_remove_repo_legacyTool(cfg), + tools_teams.CreateTeams_check_permissions_for_repo_legacyTool(cfg), + tools_teams.CreateTeams_add_or_update_repo_permissions_legacyTool(cfg), + tools_packages.CreatePackages_delete_package_version_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_get_package_version_for_authenticated_userTool(cfg), + tools_dependabot.CreateDependabot_list_alerts_for_repoTool(cfg), + tools_apps.CreateApps_get_repo_installationTool(cfg), + tools_actions.CreateActions_list_repo_workflowsTool(cfg), + tools_packages.CreatePackages_restore_package_for_authenticated_userTool(cfg), + tools_pulls.CreatePulls_submit_reviewTool(cfg), + tools_repos.CreateRepos_redeliver_webhook_deliveryTool(cfg), + tools_checks.CreateChecks_set_suites_preferencesTool(cfg), + tools_repos.CreateRepos_get_community_profile_metricsTool(cfg), + tools_orgs.CreateOrgs_assign_team_to_org_roleTool(cfg), + tools_orgs.CreateOrgs_revoke_org_role_teamTool(cfg), + tools_migrations.CreateMigrations_unlock_repo_for_authenticated_userTool(cfg), + tools_pulls.CreatePulls_list_review_commentsTool(cfg), + tools_pulls.CreatePulls_create_review_commentTool(cfg), + tools_migrations.CreateMigrations_list_repos_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_pull_requests_associated_with_commitTool(cfg), + tools_repos.CreateRepos_cancel_pages_deploymentTool(cfg), + tools_repos.CreateRepos_get_org_rulesetsTool(cfg), + tools_repos.CreateRepos_create_org_rulesetTool(cfg), + tools_activity.CreateActivity_list_received_events_for_userTool(cfg), + tools_actions.CreateActions_get_workflow_run_attemptTool(cfg), + tools_codespaces.CreateCodespaces_remove_selected_repo_from_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_add_selected_repo_to_org_secretTool(cfg), + tools_orgs.CreateOrgs_list_attestations_bulkTool(cfg), + tools_orgs.CreateOrgs_list_pat_grantsTool(cfg), + tools_orgs.CreateOrgs_update_pat_accessesTool(cfg), + tools_actions.CreateActions_list_repo_access_to_self_hosted_runner_group_in_orgTool(cfg), + tools_actions.CreateActions_set_repo_access_to_self_hosted_runner_group_in_orgTool(cfg), + tools_pulls.CreatePulls_list_reviewsTool(cfg), + tools_pulls.CreatePulls_create_reviewTool(cfg), + tools_issues.CreateIssues_list_milestonesTool(cfg), + tools_issues.CreateIssues_create_milestoneTool(cfg), + tools_users.CreateUsers_list_followers_for_userTool(cfg), + tools_packages.CreatePackages_get_all_package_versions_for_package_owned_by_userTool(cfg), + tools_packages.CreatePackages_restore_package_version_for_authenticated_userTool(cfg), + tools_issues.CreateIssues_check_user_can_be_assigned_to_issueTool(cfg), + tools_users.CreateUsers_get_authenticatedTool(cfg), + tools_users.CreateUsers_update_authenticatedTool(cfg), + tools_repos.CreateRepos_list_custom_deployment_rule_integrationsTool(cfg), + tools_orgs.CreateApi_insights_get_summary_stats_by_actorTool(cfg), + tools_repos.CreateRepos_download_tarball_archiveTool(cfg), + tools_orgs.CreateOrgs_delete_issue_typeTool(cfg), + tools_orgs.CreateOrgs_update_issue_typeTool(cfg), + tools_packages.CreatePackages_list_docker_migration_conflicting_packages_for_userTool(cfg), + tools_code_scanning.CreateCode_scanning_get_sarifTool(cfg), + tools_users.CreateUsers_get_by_usernameTool(cfg), + tools_actions.CreateActions_download_workflow_run_attempt_logsTool(cfg), + tools_activity.CreateActivity_list_repo_notifications_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_mark_repo_notifications_as_readTool(cfg), + tools_packages.CreatePackages_restore_package_for_orgTool(cfg), + tools_apps.CreateApps_list_repos_accessible_to_installationTool(cfg), + tools_actions.CreateActions_get_reviews_for_runTool(cfg), + tools_pulls.CreatePulls_update_branchTool(cfg), + tools_repos.CreateRepos_ping_webhookTool(cfg), + tools_apps.CreateApps_get_webhook_deliveryTool(cfg), + tools_billing.CreateBilling_get_github_packages_billing_userTool(cfg), + tools_repos.CreateRepos_delete_an_environmentTool(cfg), + tools_repos.CreateRepos_get_environmentTool(cfg), + tools_repos.CreateRepos_create_or_update_environmentTool(cfg), + tools_repos.CreateRepos_delete_pages_siteTool(cfg), + tools_repos.CreateRepos_get_pagesTool(cfg), + tools_repos.CreateRepos_create_pages_siteTool(cfg), + tools_repos.CreateRepos_update_information_about_pages_siteTool(cfg), + tools_apps.CreateApps_list_accounts_for_plan_stubbedTool(cfg), + tools_actions.CreateActions_update_self_hosted_runner_group_for_orgTool(cfg), + tools_actions.CreateActions_delete_self_hosted_runner_group_from_orgTool(cfg), + tools_actions.CreateActions_get_self_hosted_runner_group_for_orgTool(cfg), + tools_checks.CreateChecks_getTool(cfg), + tools_checks.CreateChecks_updateTool(cfg), + tools_codespaces.CreateCodespaces_delete_secret_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_get_secret_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_create_or_update_secret_for_authenticated_userTool(cfg), + tools_actions.CreateActions_disable_workflowTool(cfg), + tools_security_advisories.CreateSecurity_advisories_list_repository_advisoriesTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_repository_advisoryTool(cfg), + tools_repos.CreateRepos_list_invitationsTool(cfg), + tools_codespaces.CreateCodespaces_list_secrets_for_authenticated_userTool(cfg), + tools_private_registries.CreatePrivate_registries_delete_org_private_registryTool(cfg), + tools_private_registries.CreatePrivate_registries_get_org_private_registryTool(cfg), + tools_private_registries.CreatePrivate_registries_update_org_private_registryTool(cfg), + tools_codespaces.CreateCodespaces_remove_repository_for_secret_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_add_repository_for_secret_for_authenticated_userTool(cfg), + tools_issues.CreateIssues_listTool(cfg), + tools_migrations.CreateMigrations_cancel_importTool(cfg), + tools_migrations.CreateMigrations_get_import_statusTool(cfg), + tools_migrations.CreateMigrations_update_importTool(cfg), + tools_migrations.CreateMigrations_start_importTool(cfg), + tools_projects.CreateProjects_create_columnTool(cfg), + tools_projects.CreateProjects_list_columnsTool(cfg), + tools_repos.CreateRepos_test_push_webhookTool(cfg), + tools_repos.CreateRepos_get_readmeTool(cfg), + tools_issues.CreateIssues_remove_labelTool(cfg), + tools_orgs.CreateOrgs_unblock_userTool(cfg), + tools_orgs.CreateOrgs_check_blocked_userTool(cfg), + tools_orgs.CreateOrgs_block_userTool(cfg), + tools_checks.CreateChecks_createTool(cfg), + tools_git.CreateGit_get_tagTool(cfg), + tools_pulls.CreatePulls_listTool(cfg), + tools_pulls.CreatePulls_createTool(cfg), + tools_activity.CreateActivity_list_stargazers_for_repoTool(cfg), + tools_migrations.CreateMigrations_get_large_filesTool(cfg), + tools_codespaces.CreateCodespaces_get_export_details_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_org_variablesTool(cfg), + tools_actions.CreateActions_create_org_variableTool(cfg), + tools_actions.CreateActions_list_self_hosted_runner_groups_for_orgTool(cfg), + tools_actions.CreateActions_create_self_hosted_runner_group_for_orgTool(cfg), + tools_repos.CreateRepos_list_deploymentsTool(cfg), + tools_repos.CreateRepos_create_deploymentTool(cfg), + tools_gists.CreateGists_list_for_userTool(cfg), + tools_issues.CreateIssues_list_events_for_timelineTool(cfg), + tools_billing.CreateBilling_get_github_packages_billing_orgTool(cfg), + tools_users.CreateUsers_delete_ssh_signing_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_get_ssh_signing_key_for_authenticated_userTool(cfg), + tools_search.CreateSearch_codeTool(cfg), + tools_code_scanning.CreateCode_scanning_create_variant_analysisTool(cfg), + tools_codespaces.CreateCodespaces_export_for_authenticated_userTool(cfg), + tools_hosted_compute.CreateHosted_compute_delete_network_configuration_from_orgTool(cfg), + tools_hosted_compute.CreateHosted_compute_get_network_configuration_for_orgTool(cfg), + tools_hosted_compute.CreateHosted_compute_update_network_configuration_for_orgTool(cfg), + tools_repos.CreateRepos_remove_app_access_restrictionsTool(cfg), + tools_repos.CreateRepos_get_apps_with_access_to_protected_branchTool(cfg), + tools_repos.CreateRepos_add_app_access_restrictionsTool(cfg), + tools_repos.CreateRepos_set_app_access_restrictionsTool(cfg), + tools_orgs.CreateApi_insights_get_time_stats_by_actorTool(cfg), + tools_git.CreateGit_list_matching_refsTool(cfg), + tools_users.CreateUsers_delete_public_ssh_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_get_public_ssh_key_for_authenticated_userTool(cfg), + tools_apps.CreateApps_create_from_manifestTool(cfg), + tools_security_advisories.CreateSecurity_advisories_list_global_advisoriesTool(cfg), + tools_secret_scanning.CreateSecret_scanning_create_push_protection_bypassTool(cfg), + tools_orgs.CreateOrgs_revoke_org_role_userTool(cfg), + tools_orgs.CreateOrgs_assign_user_to_org_roleTool(cfg), + tools_actions.CreateActions_list_selected_repositories_enabled_github_actions_organizationTool(cfg), + tools_actions.CreateActions_set_selected_repositories_enabled_github_actions_organizationTool(cfg), + tools_codespaces.CreateCodespaces_create_with_pr_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_get_status_checks_protectionTool(cfg), + tools_repos.CreateRepos_update_status_check_protectionTool(cfg), + tools_repos.CreateRepos_remove_status_check_protectionTool(cfg), + tools_repos.CreateRepos_delete_branch_protectionTool(cfg), + tools_repos.CreateRepos_get_branch_protectionTool(cfg), + tools_repos.CreateRepos_update_branch_protectionTool(cfg), + tools_projects.CreateProjects_getTool(cfg), + tools_projects.CreateProjects_updateTool(cfg), + tools_projects.CreateProjects_deleteTool(cfg), + tools_actions.CreateActions_list_workflow_runsTool(cfg), + tools_git.CreateGit_create_treeTool(cfg), + tools_repos.CreateRepos_create_dispatch_eventTool(cfg), + tools_issues.CreateIssues_list_labels_for_milestoneTool(cfg), + tools_repos.CreateRepos_list_forksTool(cfg), + tools_repos.CreateRepos_create_forkTool(cfg), + tools_actions.CreateActions_get_hosted_runners_partner_images_for_orgTool(cfg), + tools_teams.CreateTeams_list_projects_in_orgTool(cfg), + tools_orgs.CreateOrgs_get_org_ruleset_historyTool(cfg), + tools_orgs.CreateOrgs_update_pat_accessTool(cfg), + tools_dependabot.CreateDependabot_list_org_secretsTool(cfg), + tools_git.CreateGit_create_blobTool(cfg), + tools_actions.CreateActions_download_artifactTool(cfg), + tools_orgs.CreateOrgs_listTool(cfg), + tools_search.CreateSearch_reposTool(cfg), + tools_actions.CreateActions_list_runner_applications_for_orgTool(cfg), + tools_activity.CreateActivity_list_watchers_for_repoTool(cfg), + tools_apps.CreateApps_list_installations_for_authenticated_userTool(cfg), + tools_actions.CreateActions_create_environment_variableTool(cfg), + tools_actions.CreateActions_list_environment_variablesTool(cfg), + tools_repos.CreateRepos_create_using_templateTool(cfg), + tools_repos.CreateRepos_get_participation_statsTool(cfg), + tools_security_advisories.CreateSecurity_advisories_get_global_advisoryTool(cfg), + tools_repos.CreateRepos_get_latest_releaseTool(cfg), + tools_teams.CreateTeams_list_for_authenticated_userTool(cfg), + tools_code_security.CreateCode_security_get_repositories_for_enterprise_configurationTool(cfg), + tools_projects.CreateProjects_move_cardTool(cfg), + tools_actions.CreateActions_create_remove_token_for_orgTool(cfg), + tools_gists.CreateGists_list_commentsTool(cfg), + tools_gists.CreateGists_create_commentTool(cfg), + tools_actions.CreateActions_get_environment_public_keyTool(cfg), + tools_actions.CreateActions_delete_environment_secretTool(cfg), + tools_actions.CreateActions_get_environment_secretTool(cfg), + tools_actions.CreateActions_create_or_update_environment_secretTool(cfg), + tools_issues.CreateIssues_list_comments_for_repoTool(cfg), + tools_pulls.CreatePulls_list_comments_for_reviewTool(cfg), + tools_teams.CreateTeams_list_members_legacyTool(cfg), + tools_actions.CreateActions_approve_workflow_runTool(cfg), + tools_teams.CreateTeams_delete_discussion_in_orgTool(cfg), + tools_teams.CreateTeams_get_discussion_in_orgTool(cfg), + tools_teams.CreateTeams_update_discussion_in_orgTool(cfg), + tools_repos.CreateRepos_get_repo_ruleset_versionTool(cfg), + tools_code_scanning.CreateCode_scanning_list_codeql_databasesTool(cfg), + tools_users.CreateUsers_list_attestationsTool(cfg), + tools_orgs.CreateOrgs_delete_attestations_by_subject_digestTool(cfg), + tools_repos.CreateRepos_list_webhook_deliveriesTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_alerts_for_repoTool(cfg), + tools_repos.CreateRepos_delete_commit_commentTool(cfg), + tools_repos.CreateRepos_get_commit_commentTool(cfg), + tools_repos.CreateRepos_update_commit_commentTool(cfg), + tools_codespaces.CreateCodespaces_get_repo_public_keyTool(cfg), + tools_repos.CreateRepos_get_clonesTool(cfg), + tools_issues.CreateIssues_delete_commentTool(cfg), + tools_issues.CreateIssues_get_commentTool(cfg), + tools_issues.CreateIssues_update_commentTool(cfg), + tools_actions.CreateActions_re_run_workflow_failed_jobsTool(cfg), + tools_gitignore.CreateGitignore_get_templateTool(cfg), + tools_apps.CreateApps_revoke_installation_access_tokenTool(cfg), + tools_teams.CreateTeams_list_pending_invitations_in_orgTool(cfg), + tools_orgs.CreateOrgs_cancel_invitationTool(cfg), + tools_repos.CreateRepos_get_collaborator_permission_levelTool(cfg), + tools_teams.CreateTeams_remove_membership_for_user_in_orgTool(cfg), + tools_teams.CreateTeams_get_membership_for_user_in_orgTool(cfg), + tools_teams.CreateTeams_add_or_update_membership_for_user_in_orgTool(cfg), + tools_repos.CreateRepos_get_org_rule_suitesTool(cfg), + tools_repos.CreateRepos_list_languagesTool(cfg), + } +} diff --git a/MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_org.go b/MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_org.go new file mode 100644 index 0000000..1073592 --- /dev/null +++ b/MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_org.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_add_custom_labels_to_self_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s/labels", cfg.BaseURL, org, runner_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_add_custom_labels_to_self_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_runners_runner_id_labels", + mcp.WithDescription("Add custom labels to a self-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + mcp.WithArray("labels", mcp.Required(), mcp.Description("Input parameter: The names of the custom labels to add to the runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_add_custom_labels_to_self_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_repo.go b/MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_repo.go new file mode 100644 index 0000000..f812ce5 --- /dev/null +++ b/MCP/tools/actions/actions_add_custom_labels_to_self_hosted_runner_for_repo.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_add_custom_labels_to_self_hosted_runner_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s/labels", cfg.BaseURL, owner, repo, runner_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_add_custom_labels_to_self_hosted_runner_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runners_runner_id_labels", + mcp.WithDescription("Add custom labels to a self-hosted runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + mcp.WithArray("labels", mcp.Required(), mcp.Description("Input parameter: The names of the custom labels to add to the runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_add_custom_labels_to_self_hosted_runner_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_add_repo_access_to_self_hosted_runner_group_in_org.go b/MCP/tools/actions/actions_add_repo_access_to_self_hosted_runner_group_in_org.go new file mode 100644 index 0000000..9570bea --- /dev/null +++ b/MCP/tools/actions/actions_add_repo_access_to_self_hosted_runner_group_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_add_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/repositories/%s", cfg.BaseURL, org, runner_group_id, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_add_repo_access_to_self_hosted_runner_group_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_runner-groups_runner_group_id_repositories_repository_id", + mcp.WithDescription("Add repository access to a self-hosted runner group in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The unique identifier of the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_add_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_add_selected_repo_to_org_secret.go b/MCP/tools/actions/actions_add_selected_repo_to_org_secret.go new file mode 100644 index 0000000..4966c97 --- /dev/null +++ b/MCP/tools/actions/actions_add_selected_repo_to_org_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_add_selected_repo_to_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s/repositories/%s", cfg.BaseURL, org, secret_name, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_add_selected_repo_to_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Add selected repository to an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_add_selected_repo_to_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_add_selected_repo_to_org_variable.go b/MCP/tools/actions/actions_add_selected_repo_to_org_variable.go new file mode 100644 index 0000000..dc0724b --- /dev/null +++ b/MCP/tools/actions/actions_add_selected_repo_to_org_variable.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_add_selected_repo_to_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s/repositories/%s", cfg.BaseURL, org, name, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_add_selected_repo_to_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_variables_name_repositories_repository_id", + mcp.WithDescription("Add selected repository to an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_add_selected_repo_to_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_add_self_hosted_runner_to_group_for_org.go b/MCP/tools/actions/actions_add_self_hosted_runner_to_group_for_org.go new file mode 100644 index 0000000..0613415 --- /dev/null +++ b/MCP/tools/actions/actions_add_self_hosted_runner_to_group_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_add_self_hosted_runner_to_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/runners/%s", cfg.BaseURL, org, runner_group_id, runner_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_add_self_hosted_runner_to_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_runner-groups_runner_group_id_runners_runner_id", + mcp.WithDescription("Add a self-hosted runner to a group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_add_self_hosted_runner_to_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_approve_workflow_run.go b/MCP/tools/actions/actions_approve_workflow_run.go new file mode 100644 index 0000000..3d97f7c --- /dev/null +++ b/MCP/tools/actions/actions_approve_workflow_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_approve_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/approve", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_approve_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_approve", + mcp.WithDescription("Approve a workflow run for a fork pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_approve_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_cancel_workflow_run.go b/MCP/tools/actions/actions_cancel_workflow_run.go new file mode 100644 index 0000000..cbd8b42 --- /dev/null +++ b/MCP/tools/actions/actions_cancel_workflow_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_cancel_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/cancel", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_cancel_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_cancel", + mcp.WithDescription("Cancel a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_cancel_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_environment_variable.go b/MCP/tools/actions/actions_create_environment_variable.go new file mode 100644 index 0000000..894b26a --- /dev/null +++ b/MCP/tools/actions/actions_create_environment_variable.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_environment_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/variables", cfg.BaseURL, owner, repo, environment_name) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_environment_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_environments_environment_name_variables", + mcp.WithDescription("Create an environment variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the variable.")), + mcp.WithString("value", mcp.Required(), mcp.Description("Input parameter: The value of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_environment_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_hosted_runner_for_org.go b/MCP/tools/actions/actions_create_hosted_runner_for_org.go new file mode 100644 index 0000000..55c1ee3 --- /dev/null +++ b/MCP/tools/actions/actions_create_hosted_runner_for_org.go @@ -0,0 +1,101 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_hosted-runners", + mcp.WithDescription("Create a GitHub-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("maximum_runners", mcp.Description("Input parameter: The maximum amount of runners to scale up to. Runners will not auto-scale above this number. Use this setting to limit your cost.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the runner. Must be between 1 and 64 characters and may only contain upper and lowercase letters a-z, numbers 0-9, '.', '-', and '_'.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Input parameter: The existing runner group to add this runner to.")), + mcp.WithString("size", mcp.Required(), mcp.Description("Input parameter: The machine size of the runner. To list available sizes, use `GET actions/hosted-runners/machine-sizes`")), + mcp.WithBoolean("enable_static_ip", mcp.Description("Input parameter: Whether this runner should be created with a static public IP. Note limit on account. To list limits on account, use `GET actions/hosted-runners/limits`")), + mcp.WithObject("image", mcp.Required(), mcp.Description("Input parameter: The image of runner. To list all available images, use `GET /actions/hosted-runners/images/github-owned` or `GET /actions/hosted-runners/images/partner`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_or_update_environment_secret.go b/MCP/tools/actions/actions_create_or_update_environment_secret.go new file mode 100644 index 0000000..d7dfea1 --- /dev/null +++ b/MCP/tools/actions/actions_create_or_update_environment_secret.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_or_update_environment_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/secrets/%s", cfg.BaseURL, owner, repo, environment_name, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_or_update_environment_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_environments_environment_name_secrets_secret_name", + mcp.WithDescription("Create or update an environment secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("encrypted_value", mcp.Required(), mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get an environment public key](https://docs.github.com/rest/actions/secrets#get-an-environment-public-key) endpoint.")), + mcp.WithString("key_id", mcp.Required(), mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_or_update_environment_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_or_update_org_secret.go b/MCP/tools/actions/actions_create_or_update_org_secret.go new file mode 100644 index 0000000..7311187 --- /dev/null +++ b/MCP/tools/actions/actions_create_or_update_org_secret.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_or_update_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_or_update_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_secrets_secret_name", + mcp.WithDescription("Create or update an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("encrypted_value", mcp.Required(), mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get an organization public key](https://docs.github.com/rest/actions/secrets#get-an-organization-public-key) endpoint.")), + mcp.WithString("key_id", mcp.Required(), mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository ids that can access the organization secret. You can only provide a list of repository ids when the `visibility` is set to `selected`. You can manage the list of selected repositories using the [List selected repositories for an organization secret](https://docs.github.com/rest/actions/secrets#list-selected-repositories-for-an-organization-secret), [Set selected repositories for an organization secret](https://docs.github.com/rest/actions/secrets#set-selected-repositories-for-an-organization-secret), and [Remove selected repository from an organization secret](https://docs.github.com/rest/actions/secrets#remove-selected-repository-from-an-organization-secret) endpoints.")), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: Which type of organization repositories have access to the organization secret. `selected` means only the repositories specified by `selected_repository_ids` can access the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_or_update_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_or_update_repo_secret.go b/MCP/tools/actions/actions_create_or_update_repo_secret.go new file mode 100644 index 0000000..848a507 --- /dev/null +++ b/MCP/tools/actions/actions_create_or_update_repo_secret.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_or_update_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_or_update_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_secrets_secret_name", + mcp.WithDescription("Create or update a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("encrypted_value", mcp.Required(), mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get a repository public key](https://docs.github.com/rest/actions/secrets#get-a-repository-public-key) endpoint.")), + mcp.WithString("key_id", mcp.Required(), mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_or_update_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_org_variable.go b/MCP/tools/actions/actions_create_org_variable.go new file mode 100644 index 0000000..ce313a4 --- /dev/null +++ b/MCP/tools/actions/actions_create_org_variable.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_variables", + mcp.WithDescription("Create an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: The type of repositories in the organization that can access the variable. `selected` means only the repositories specified by `selected_repository_ids` can access the variable.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the variable.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository ids that can access the organization variable. You can only provide a list of repository ids when the `visibility` is set to `selected`.")), + mcp.WithString("value", mcp.Required(), mcp.Description("Input parameter: The value of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_registration_token_for_org.go b/MCP/tools/actions/actions_create_registration_token_for_org.go new file mode 100644 index 0000000..9e9a9ac --- /dev/null +++ b/MCP/tools/actions/actions_create_registration_token_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_registration_token_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/registration-token", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_registration_token_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_runners_registration-token", + mcp.WithDescription("Create a registration token for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_registration_token_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_registration_token_for_repo.go b/MCP/tools/actions/actions_create_registration_token_for_repo.go new file mode 100644 index 0000000..9397a60 --- /dev/null +++ b/MCP/tools/actions/actions_create_registration_token_for_repo.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_registration_token_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/registration-token", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_registration_token_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runners_registration-token", + mcp.WithDescription("Create a registration token for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_registration_token_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_remove_token_for_org.go b/MCP/tools/actions/actions_create_remove_token_for_org.go new file mode 100644 index 0000000..fd57c2e --- /dev/null +++ b/MCP/tools/actions/actions_create_remove_token_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_remove_token_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/remove-token", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_remove_token_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_runners_remove-token", + mcp.WithDescription("Create a remove token for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_remove_token_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_remove_token_for_repo.go b/MCP/tools/actions/actions_create_remove_token_for_repo.go new file mode 100644 index 0000000..ec08f5a --- /dev/null +++ b/MCP/tools/actions/actions_create_remove_token_for_repo.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_remove_token_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/remove-token", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_remove_token_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runners_remove-token", + mcp.WithDescription("Create a remove token for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_remove_token_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_repo_variable.go b/MCP/tools/actions/actions_create_repo_variable.go new file mode 100644 index 0000000..c7d56df --- /dev/null +++ b/MCP/tools/actions/actions_create_repo_variable.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_repo_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/variables", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_repo_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_variables", + mcp.WithDescription("Create a repository variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the variable.")), + mcp.WithString("value", mcp.Required(), mcp.Description("Input parameter: The value of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_repo_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_self_hosted_runner_group_for_org.go b/MCP/tools/actions/actions_create_self_hosted_runner_group_for_org.go new file mode 100644 index 0000000..8b8aaf8 --- /dev/null +++ b/MCP/tools/actions/actions_create_self_hosted_runner_group_for_org.go @@ -0,0 +1,103 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_self_hosted_runner_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_self_hosted_runner_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_runner-groups", + mcp.WithDescription("Create a self-hosted runner group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("network_configuration_id", mcp.Description("Input parameter: The identifier of a hosted compute network configuration.")), + mcp.WithBoolean("restricted_to_workflows", mcp.Description("Input parameter: If `true`, the runner group will be restricted to running only the workflows specified in the `selected_workflows` array.")), + mcp.WithArray("runners", mcp.Description("Input parameter: List of runner IDs to add to the runner group.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: List of repository IDs that can access the runner group.")), + mcp.WithArray("selected_workflows", mcp.Description("Input parameter: List of workflows the runner group should be allowed to run. This setting will be ignored unless `restricted_to_workflows` is set to `true`.")), + mcp.WithString("visibility", mcp.Description("Input parameter: Visibility of a runner group. You can select all repositories, select individual repositories, or limit access to private repositories.")), + mcp.WithBoolean("allows_public_repositories", mcp.Description("Input parameter: Whether the runner group can be used by `public` repositories.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the runner group.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_self_hosted_runner_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_create_workflow_dispatch.go b/MCP/tools/actions/actions_create_workflow_dispatch.go new file mode 100644 index 0000000..3d3f66e --- /dev/null +++ b/MCP/tools/actions/actions_create_workflow_dispatch.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_create_workflow_dispatchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + workflow_idVal, ok := args["workflow_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: workflow_id"), nil + } + workflow_id, ok := workflow_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: workflow_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows/%s/dispatches", cfg.BaseURL, owner, repo, workflow_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_create_workflow_dispatchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_workflows_workflow_id_dispatches", + mcp.WithDescription("Create a workflow dispatch event"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("workflow_id", mcp.Required(), mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string.")), + mcp.WithObject("inputs", mcp.Description("Input parameter: Input keys and values configured in the workflow file. The maximum number of properties is 10. Any default properties configured in the workflow file will be used when `inputs` are omitted.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("Input parameter: The git reference for the workflow. The reference can be a branch or tag name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_create_workflow_dispatchHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_actions_cache_by_id.go b/MCP/tools/actions/actions_delete_actions_cache_by_id.go new file mode 100644 index 0000000..fdfc6a2 --- /dev/null +++ b/MCP/tools/actions/actions_delete_actions_cache_by_id.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_actions_cache_by_idHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + cache_idVal, ok := args["cache_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: cache_id"), nil + } + cache_id, ok := cache_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: cache_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/caches/%s", cfg.BaseURL, owner, repo, cache_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_actions_cache_by_idTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_caches_cache_id", + mcp.WithDescription("Delete a GitHub Actions cache for a repository (using a cache ID)"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("cache_id", mcp.Required(), mcp.Description("The unique identifier of the GitHub Actions cache.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_actions_cache_by_idHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_actions_cache_by_key.go b/MCP/tools/actions/actions_delete_actions_cache_by_key.go new file mode 100644 index 0000000..63a56bd --- /dev/null +++ b/MCP/tools/actions/actions_delete_actions_cache_by_key.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_actions_cache_by_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["key"]; ok { + queryParams = append(queryParams, fmt.Sprintf("key=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/caches%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_actions_cache_by_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_caches", + mcp.WithDescription("Delete GitHub Actions caches for a repository (using a cache key)"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("key", mcp.Required(), mcp.Description("A key for identifying the cache.")), + mcp.WithString("ref", mcp.Description("The full Git reference for narrowing down the cache. The `ref` for a branch should be formatted as `refs/heads/`. To reference a pull request use `refs/pull//merge`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_actions_cache_by_keyHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_artifact.go b/MCP/tools/actions/actions_delete_artifact.go new file mode 100644 index 0000000..74fa925 --- /dev/null +++ b/MCP/tools/actions/actions_delete_artifact.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_artifactHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + artifact_idVal, ok := args["artifact_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: artifact_id"), nil + } + artifact_id, ok := artifact_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: artifact_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/artifacts/%s", cfg.BaseURL, owner, repo, artifact_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_artifactTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_artifacts_artifact_id", + mcp.WithDescription("Delete an artifact"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("artifact_id", mcp.Required(), mcp.Description("The unique identifier of the artifact.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_artifactHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_environment_secret.go b/MCP/tools/actions/actions_delete_environment_secret.go new file mode 100644 index 0000000..c67b70e --- /dev/null +++ b/MCP/tools/actions/actions_delete_environment_secret.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_environment_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/secrets/%s", cfg.BaseURL, owner, repo, environment_name, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_environment_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_environments_environment_name_secrets_secret_name", + mcp.WithDescription("Delete an environment secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_environment_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_environment_variable.go b/MCP/tools/actions/actions_delete_environment_variable.go new file mode 100644 index 0000000..46367a5 --- /dev/null +++ b/MCP/tools/actions/actions_delete_environment_variable.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_environment_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/variables/%s", cfg.BaseURL, owner, repo, name, environment_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_environment_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_environments_environment_name_variables_name", + mcp.WithDescription("Delete an environment variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_environment_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_hosted_runner_for_org.go b/MCP/tools/actions/actions_delete_hosted_runner_for_org.go new file mode 100644 index 0000000..a2f885f --- /dev/null +++ b/MCP/tools/actions/actions_delete_hosted_runner_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hosted_runner_idVal, ok := args["hosted_runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hosted_runner_id"), nil + } + hosted_runner_id, ok := hosted_runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hosted_runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/%s", cfg.BaseURL, org, hosted_runner_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_hosted-runners_hosted_runner_id", + mcp.WithDescription("Delete a GitHub-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hosted_runner_id", mcp.Required(), mcp.Description("Unique identifier of the GitHub-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_org_secret.go b/MCP/tools/actions/actions_delete_org_secret.go new file mode 100644 index 0000000..0a52c6b --- /dev/null +++ b/MCP/tools/actions/actions_delete_org_secret.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_secrets_secret_name", + mcp.WithDescription("Delete an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_org_variable.go b/MCP/tools/actions/actions_delete_org_variable.go new file mode 100644 index 0000000..cea29c9 --- /dev/null +++ b/MCP/tools/actions/actions_delete_org_variable.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s", cfg.BaseURL, org, name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_variables_name", + mcp.WithDescription("Delete an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_repo_secret.go b/MCP/tools/actions/actions_delete_repo_secret.go new file mode 100644 index 0000000..0e95259 --- /dev/null +++ b/MCP/tools/actions/actions_delete_repo_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_secrets_secret_name", + mcp.WithDescription("Delete a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_repo_variable.go b/MCP/tools/actions/actions_delete_repo_variable.go new file mode 100644 index 0000000..edcf1e7 --- /dev/null +++ b/MCP/tools/actions/actions_delete_repo_variable.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_repo_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/variables/%s", cfg.BaseURL, owner, repo, name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_repo_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_variables_name", + mcp.WithDescription("Delete a repository variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_repo_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_self_hosted_runner_from_org.go b/MCP/tools/actions/actions_delete_self_hosted_runner_from_org.go new file mode 100644 index 0000000..2e39688 --- /dev/null +++ b/MCP/tools/actions/actions_delete_self_hosted_runner_from_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_self_hosted_runner_from_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s", cfg.BaseURL, org, runner_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_self_hosted_runner_from_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_runners_runner_id", + mcp.WithDescription("Delete a self-hosted runner from an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_self_hosted_runner_from_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_self_hosted_runner_from_repo.go b/MCP/tools/actions/actions_delete_self_hosted_runner_from_repo.go new file mode 100644 index 0000000..bc92441 --- /dev/null +++ b/MCP/tools/actions/actions_delete_self_hosted_runner_from_repo.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_self_hosted_runner_from_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s", cfg.BaseURL, owner, repo, runner_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_self_hosted_runner_from_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_runners_runner_id", + mcp.WithDescription("Delete a self-hosted runner from a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_self_hosted_runner_from_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_self_hosted_runner_group_from_org.go b/MCP/tools/actions/actions_delete_self_hosted_runner_group_from_org.go new file mode 100644 index 0000000..0432134 --- /dev/null +++ b/MCP/tools/actions/actions_delete_self_hosted_runner_group_from_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_self_hosted_runner_group_from_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s", cfg.BaseURL, org, runner_group_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_self_hosted_runner_group_from_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_runner-groups_runner_group_id", + mcp.WithDescription("Delete a self-hosted runner group from an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_self_hosted_runner_group_from_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_workflow_run.go b/MCP/tools/actions/actions_delete_workflow_run.go new file mode 100644 index 0000000..c54c87a --- /dev/null +++ b/MCP/tools/actions/actions_delete_workflow_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_runs_run_id", + mcp.WithDescription("Delete a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_delete_workflow_run_logs.go b/MCP/tools/actions/actions_delete_workflow_run_logs.go new file mode 100644 index 0000000..27e7920 --- /dev/null +++ b/MCP/tools/actions/actions_delete_workflow_run_logs.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_delete_workflow_run_logsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/logs", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_delete_workflow_run_logsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_runs_run_id_logs", + mcp.WithDescription("Delete workflow run logs"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_delete_workflow_run_logsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_disable_selected_repository_github_actions_organization.go b/MCP/tools/actions/actions_disable_selected_repository_github_actions_organization.go new file mode 100644 index 0000000..146ad07 --- /dev/null +++ b/MCP/tools/actions/actions_disable_selected_repository_github_actions_organization.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_disable_selected_repository_github_actions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/repositories/%s", cfg.BaseURL, org, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_disable_selected_repository_github_actions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_permissions_repositories_repository_id", + mcp.WithDescription("Disable a selected repository for GitHub Actions in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The unique identifier of the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_disable_selected_repository_github_actions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_disable_workflow.go b/MCP/tools/actions/actions_disable_workflow.go new file mode 100644 index 0000000..3cb5f11 --- /dev/null +++ b/MCP/tools/actions/actions_disable_workflow.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_disable_workflowHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + workflow_idVal, ok := args["workflow_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: workflow_id"), nil + } + workflow_id, ok := workflow_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: workflow_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows/%s/disable", cfg.BaseURL, owner, repo, workflow_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_disable_workflowTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_workflows_workflow_id_disable", + mcp.WithDescription("Disable a workflow"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("workflow_id", mcp.Required(), mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_disable_workflowHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_download_artifact.go b/MCP/tools/actions/actions_download_artifact.go new file mode 100644 index 0000000..da02ffe --- /dev/null +++ b/MCP/tools/actions/actions_download_artifact.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_download_artifactHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + artifact_idVal, ok := args["artifact_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: artifact_id"), nil + } + artifact_id, ok := artifact_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: artifact_id"), nil + } + archive_formatVal, ok := args["archive_format"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: archive_format"), nil + } + archive_format, ok := archive_formatVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: archive_format"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/artifacts/%s/%s", cfg.BaseURL, owner, repo, artifact_id, archive_format) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_download_artifactTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_artifacts_artifact_id_archive_format", + mcp.WithDescription("Download an artifact"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("artifact_id", mcp.Required(), mcp.Description("The unique identifier of the artifact.")), + mcp.WithString("archive_format", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_download_artifactHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_download_job_logs_for_workflow_run.go b/MCP/tools/actions/actions_download_job_logs_for_workflow_run.go new file mode 100644 index 0000000..b9709fa --- /dev/null +++ b/MCP/tools/actions/actions_download_job_logs_for_workflow_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_download_job_logs_for_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + job_idVal, ok := args["job_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: job_id"), nil + } + job_id, ok := job_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: job_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/jobs/%s/logs", cfg.BaseURL, owner, repo, job_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_download_job_logs_for_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_jobs_job_id_logs", + mcp.WithDescription("Download job logs for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("job_id", mcp.Required(), mcp.Description("The unique identifier of the job.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_download_job_logs_for_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_download_workflow_run_attempt_logs.go b/MCP/tools/actions/actions_download_workflow_run_attempt_logs.go new file mode 100644 index 0000000..b06ed23 --- /dev/null +++ b/MCP/tools/actions/actions_download_workflow_run_attempt_logs.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_download_workflow_run_attempt_logsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + attempt_numberVal, ok := args["attempt_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: attempt_number"), nil + } + attempt_number, ok := attempt_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: attempt_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/attempts/%s/logs", cfg.BaseURL, owner, repo, run_id, attempt_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_download_workflow_run_attempt_logsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_attempts_attempt_number_logs", + mcp.WithDescription("Download workflow run attempt logs"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithNumber("attempt_number", mcp.Required(), mcp.Description("The attempt number of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_download_workflow_run_attempt_logsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_download_workflow_run_logs.go b/MCP/tools/actions/actions_download_workflow_run_logs.go new file mode 100644 index 0000000..afff023 --- /dev/null +++ b/MCP/tools/actions/actions_download_workflow_run_logs.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_download_workflow_run_logsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/logs", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_download_workflow_run_logsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_logs", + mcp.WithDescription("Download workflow run logs"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_download_workflow_run_logsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_enable_selected_repository_github_actions_organization.go b/MCP/tools/actions/actions_enable_selected_repository_github_actions_organization.go new file mode 100644 index 0000000..2f84ae2 --- /dev/null +++ b/MCP/tools/actions/actions_enable_selected_repository_github_actions_organization.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_enable_selected_repository_github_actions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/repositories/%s", cfg.BaseURL, org, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_enable_selected_repository_github_actions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_permissions_repositories_repository_id", + mcp.WithDescription("Enable a selected repository for GitHub Actions in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The unique identifier of the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_enable_selected_repository_github_actions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_enable_workflow.go b/MCP/tools/actions/actions_enable_workflow.go new file mode 100644 index 0000000..f8d24f0 --- /dev/null +++ b/MCP/tools/actions/actions_enable_workflow.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_enable_workflowHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + workflow_idVal, ok := args["workflow_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: workflow_id"), nil + } + workflow_id, ok := workflow_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: workflow_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows/%s/enable", cfg.BaseURL, owner, repo, workflow_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_enable_workflowTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_workflows_workflow_id_enable", + mcp.WithDescription("Enable a workflow"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("workflow_id", mcp.Required(), mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_enable_workflowHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_force_cancel_workflow_run.go b/MCP/tools/actions/actions_force_cancel_workflow_run.go new file mode 100644 index 0000000..a891263 --- /dev/null +++ b/MCP/tools/actions/actions_force_cancel_workflow_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_force_cancel_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/force-cancel", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_force_cancel_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_force-cancel", + mcp.WithDescription("Force cancel a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_force_cancel_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_generate_runner_jitconfig_for_org.go b/MCP/tools/actions/actions_generate_runner_jitconfig_for_org.go new file mode 100644 index 0000000..12790dd --- /dev/null +++ b/MCP/tools/actions/actions_generate_runner_jitconfig_for_org.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_generate_runner_jitconfig_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/generate-jitconfig", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_generate_runner_jitconfig_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_actions_runners_generate-jitconfig", + mcp.WithDescription("Create configuration for a just-in-time runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("labels", mcp.Required(), mcp.Description("Input parameter: The names of the custom labels to add to the runner. **Minimum items**: 1. **Maximum items**: 100.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the new runner.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Input parameter: The ID of the runner group to register the runner to.")), + mcp.WithString("work_folder", mcp.Description("Input parameter: The working directory to be used for job execution, relative to the runner install directory.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_generate_runner_jitconfig_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_generate_runner_jitconfig_for_repo.go b/MCP/tools/actions/actions_generate_runner_jitconfig_for_repo.go new file mode 100644 index 0000000..58b4d2f --- /dev/null +++ b/MCP/tools/actions/actions_generate_runner_jitconfig_for_repo.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_generate_runner_jitconfig_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/generate-jitconfig", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_generate_runner_jitconfig_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runners_generate-jitconfig", + mcp.WithDescription("Create configuration for a just-in-time runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the new runner.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Input parameter: The ID of the runner group to register the runner to.")), + mcp.WithString("work_folder", mcp.Description("Input parameter: The working directory to be used for job execution, relative to the runner install directory.")), + mcp.WithArray("labels", mcp.Required(), mcp.Description("Input parameter: The names of the custom labels to add to the runner. **Minimum items**: 1. **Maximum items**: 100.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_generate_runner_jitconfig_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_actions_cache_list.go b/MCP/tools/actions/actions_get_actions_cache_list.go new file mode 100644 index 0000000..ebcb788 --- /dev/null +++ b/MCP/tools/actions/actions_get_actions_cache_list.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_actions_cache_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["key"]; ok { + queryParams = append(queryParams, fmt.Sprintf("key=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/caches%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_actions_cache_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_caches", + mcp.WithDescription("List GitHub Actions caches for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("ref", mcp.Description("The full Git reference for narrowing down the cache. The `ref` for a branch should be formatted as `refs/heads/`. To reference a pull request use `refs/pull//merge`.")), + mcp.WithString("key", mcp.Description("An explicit key or prefix for identifying the cache")), + mcp.WithString("sort", mcp.Description("The property to sort the results by. `created_at` means when the cache was created. `last_accessed_at` means when the cache was last accessed. `size_in_bytes` is the size of the cache in bytes.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_actions_cache_listHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_actions_cache_usage.go b/MCP/tools/actions/actions_get_actions_cache_usage.go new file mode 100644 index 0000000..2809157 --- /dev/null +++ b/MCP/tools/actions/actions_get_actions_cache_usage.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_actions_cache_usageHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/cache/usage", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_actions_cache_usageTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_cache_usage", + mcp.WithDescription("Get GitHub Actions cache usage for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_actions_cache_usageHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_actions_cache_usage_by_repo_for_org.go b/MCP/tools/actions/actions_get_actions_cache_usage_by_repo_for_org.go new file mode 100644 index 0000000..991af1f --- /dev/null +++ b/MCP/tools/actions/actions_get_actions_cache_usage_by_repo_for_org.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_actions_cache_usage_by_repo_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/cache/usage-by-repository%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_actions_cache_usage_by_repo_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_cache_usage-by-repository", + mcp.WithDescription("List repositories with GitHub Actions cache usage for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_actions_cache_usage_by_repo_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_actions_cache_usage_for_org.go b/MCP/tools/actions/actions_get_actions_cache_usage_for_org.go new file mode 100644 index 0000000..e5d433e --- /dev/null +++ b/MCP/tools/actions/actions_get_actions_cache_usage_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_actions_cache_usage_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/cache/usage", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_actions_cache_usage_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_cache_usage", + mcp.WithDescription("Get GitHub Actions cache usage for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_actions_cache_usage_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_allowed_actions_organization.go b/MCP/tools/actions/actions_get_allowed_actions_organization.go new file mode 100644 index 0000000..b6f6255 --- /dev/null +++ b/MCP/tools/actions/actions_get_allowed_actions_organization.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_allowed_actions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/selected-actions", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_allowed_actions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_permissions_selected-actions", + mcp.WithDescription("Get allowed actions and reusable workflows for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_allowed_actions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_allowed_actions_repository.go b/MCP/tools/actions/actions_get_allowed_actions_repository.go new file mode 100644 index 0000000..459119e --- /dev/null +++ b/MCP/tools/actions/actions_get_allowed_actions_repository.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_allowed_actions_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions/selected-actions", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_allowed_actions_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_permissions_selected-actions", + mcp.WithDescription("Get allowed actions and reusable workflows for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_allowed_actions_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_artifact.go b/MCP/tools/actions/actions_get_artifact.go new file mode 100644 index 0000000..cce7da2 --- /dev/null +++ b/MCP/tools/actions/actions_get_artifact.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_artifactHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + artifact_idVal, ok := args["artifact_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: artifact_id"), nil + } + artifact_id, ok := artifact_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: artifact_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/artifacts/%s", cfg.BaseURL, owner, repo, artifact_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Artifact + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_artifactTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_artifacts_artifact_id", + mcp.WithDescription("Get an artifact"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("artifact_id", mcp.Required(), mcp.Description("The unique identifier of the artifact.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_artifactHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_custom_oidc_sub_claim_for_repo.go b/MCP/tools/actions/actions_get_custom_oidc_sub_claim_for_repo.go new file mode 100644 index 0000000..ee85f01 --- /dev/null +++ b/MCP/tools/actions/actions_get_custom_oidc_sub_claim_for_repo.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_custom_oidc_sub_claim_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/oidc/customization/sub", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_custom_oidc_sub_claim_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_oidc_customization_sub", + mcp.WithDescription("Get the customization template for an OIDC subject claim for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_custom_oidc_sub_claim_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_environment_public_key.go b/MCP/tools/actions/actions_get_environment_public_key.go new file mode 100644 index 0000000..9156e47 --- /dev/null +++ b/MCP/tools/actions/actions_get_environment_public_key.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_environment_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/secrets/public-key", cfg.BaseURL, owner, repo, environment_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_environment_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_secrets_public-key", + mcp.WithDescription("Get an environment public key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_environment_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_environment_secret.go b/MCP/tools/actions/actions_get_environment_secret.go new file mode 100644 index 0000000..d41f192 --- /dev/null +++ b/MCP/tools/actions/actions_get_environment_secret.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_environment_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/secrets/%s", cfg.BaseURL, owner, repo, environment_name, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_environment_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_secrets_secret_name", + mcp.WithDescription("Get an environment secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_environment_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_environment_variable.go b/MCP/tools/actions/actions_get_environment_variable.go new file mode 100644 index 0000000..2c10c1c --- /dev/null +++ b/MCP/tools/actions/actions_get_environment_variable.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_environment_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/variables/%s", cfg.BaseURL, owner, repo, environment_name, name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_environment_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_variables_name", + mcp.WithDescription("Get an environment variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_environment_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_organization.go b/MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_organization.go new file mode 100644 index 0000000..fc8256a --- /dev/null +++ b/MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_organization.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_github_actions_default_workflow_permissions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/workflow", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_github_actions_default_workflow_permissions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_permissions_workflow", + mcp.WithDescription("Get default workflow permissions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_github_actions_default_workflow_permissions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_repository.go b/MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_repository.go new file mode 100644 index 0000000..5b425b7 --- /dev/null +++ b/MCP/tools/actions/actions_get_github_actions_default_workflow_permissions_repository.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_github_actions_default_workflow_permissions_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions/workflow", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_github_actions_default_workflow_permissions_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_permissions_workflow", + mcp.WithDescription("Get default workflow permissions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_github_actions_default_workflow_permissions_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_github_actions_permissions_organization.go b/MCP/tools/actions/actions_get_github_actions_permissions_organization.go new file mode 100644 index 0000000..a78343e --- /dev/null +++ b/MCP/tools/actions/actions_get_github_actions_permissions_organization.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_github_actions_permissions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_github_actions_permissions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_permissions", + mcp.WithDescription("Get GitHub Actions permissions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_github_actions_permissions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_github_actions_permissions_repository.go b/MCP/tools/actions/actions_get_github_actions_permissions_repository.go new file mode 100644 index 0000000..45d8df5 --- /dev/null +++ b/MCP/tools/actions/actions_get_github_actions_permissions_repository.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_github_actions_permissions_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_github_actions_permissions_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_permissions", + mcp.WithDescription("Get GitHub Actions permissions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_github_actions_permissions_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_hosted_runner_for_org.go b/MCP/tools/actions/actions_get_hosted_runner_for_org.go new file mode 100644 index 0000000..e62945c --- /dev/null +++ b/MCP/tools/actions/actions_get_hosted_runner_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hosted_runner_idVal, ok := args["hosted_runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hosted_runner_id"), nil + } + hosted_runner_id, ok := hosted_runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hosted_runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/%s", cfg.BaseURL, org, hosted_runner_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners_hosted_runner_id", + mcp.WithDescription("Get a GitHub-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hosted_runner_id", mcp.Required(), mcp.Description("Unique identifier of the GitHub-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_hosted_runners_github_owned_images_for_org.go b/MCP/tools/actions/actions_get_hosted_runners_github_owned_images_for_org.go new file mode 100644 index 0000000..cc5bddc --- /dev/null +++ b/MCP/tools/actions/actions_get_hosted_runners_github_owned_images_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_hosted_runners_github_owned_images_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/images/github-owned", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_hosted_runners_github_owned_images_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners_images_github-owned", + mcp.WithDescription("Get GitHub-owned images for GitHub-hosted runners in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_hosted_runners_github_owned_images_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_hosted_runners_limits_for_org.go b/MCP/tools/actions/actions_get_hosted_runners_limits_for_org.go new file mode 100644 index 0000000..ddae2fa --- /dev/null +++ b/MCP/tools/actions/actions_get_hosted_runners_limits_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_hosted_runners_limits_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/limits", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_hosted_runners_limits_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners_limits", + mcp.WithDescription("Get limits on GitHub-hosted runners for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_hosted_runners_limits_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_hosted_runners_machine_specs_for_org.go b/MCP/tools/actions/actions_get_hosted_runners_machine_specs_for_org.go new file mode 100644 index 0000000..fc21b83 --- /dev/null +++ b/MCP/tools/actions/actions_get_hosted_runners_machine_specs_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_hosted_runners_machine_specs_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/machine-sizes", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_hosted_runners_machine_specs_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners_machine-sizes", + mcp.WithDescription("Get GitHub-hosted runners machine specs for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_hosted_runners_machine_specs_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_hosted_runners_partner_images_for_org.go b/MCP/tools/actions/actions_get_hosted_runners_partner_images_for_org.go new file mode 100644 index 0000000..ec9d218 --- /dev/null +++ b/MCP/tools/actions/actions_get_hosted_runners_partner_images_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_hosted_runners_partner_images_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/images/partner", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_hosted_runners_partner_images_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners_images_partner", + mcp.WithDescription("Get partner images for GitHub-hosted runners in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_hosted_runners_partner_images_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_hosted_runners_platforms_for_org.go b/MCP/tools/actions/actions_get_hosted_runners_platforms_for_org.go new file mode 100644 index 0000000..2ad5133 --- /dev/null +++ b/MCP/tools/actions/actions_get_hosted_runners_platforms_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_hosted_runners_platforms_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/platforms", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_hosted_runners_platforms_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners_platforms", + mcp.WithDescription("Get platforms for GitHub-hosted runners in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_hosted_runners_platforms_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_job_for_workflow_run.go b/MCP/tools/actions/actions_get_job_for_workflow_run.go new file mode 100644 index 0000000..0d13efa --- /dev/null +++ b/MCP/tools/actions/actions_get_job_for_workflow_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_job_for_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + job_idVal, ok := args["job_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: job_id"), nil + } + job_id, ok := job_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: job_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/jobs/%s", cfg.BaseURL, owner, repo, job_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Job + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_job_for_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_jobs_job_id", + mcp.WithDescription("Get a job for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("job_id", mcp.Required(), mcp.Description("The unique identifier of the job.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_job_for_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_org_public_key.go b/MCP/tools/actions/actions_get_org_public_key.go new file mode 100644 index 0000000..f631f07 --- /dev/null +++ b/MCP/tools/actions/actions_get_org_public_key.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_org_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/public-key", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_org_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_secrets_public-key", + mcp.WithDescription("Get an organization public key"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_org_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_org_secret.go b/MCP/tools/actions/actions_get_org_secret.go new file mode 100644 index 0000000..e68071a --- /dev/null +++ b/MCP/tools/actions/actions_get_org_secret.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_secrets_secret_name", + mcp.WithDescription("Get an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_org_variable.go b/MCP/tools/actions/actions_get_org_variable.go new file mode 100644 index 0000000..88b8f5f --- /dev/null +++ b/MCP/tools/actions/actions_get_org_variable.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s", cfg.BaseURL, org, name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_variables_name", + mcp.WithDescription("Get an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_pending_deployments_for_run.go b/MCP/tools/actions/actions_get_pending_deployments_for_run.go new file mode 100644 index 0000000..b39133c --- /dev/null +++ b/MCP/tools/actions/actions_get_pending_deployments_for_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_pending_deployments_for_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/pending_deployments", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_pending_deployments_for_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_pending_deployments", + mcp.WithDescription("Get pending deployments for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_pending_deployments_for_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_repo_public_key.go b/MCP/tools/actions/actions_get_repo_public_key.go new file mode 100644 index 0000000..8d0510d --- /dev/null +++ b/MCP/tools/actions/actions_get_repo_public_key.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_repo_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/secrets/public-key", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_repo_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_secrets_public-key", + mcp.WithDescription("Get a repository public key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_repo_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_repo_secret.go b/MCP/tools/actions/actions_get_repo_secret.go new file mode 100644 index 0000000..c2c1923 --- /dev/null +++ b/MCP/tools/actions/actions_get_repo_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_secrets_secret_name", + mcp.WithDescription("Get a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_repo_variable.go b/MCP/tools/actions/actions_get_repo_variable.go new file mode 100644 index 0000000..6c357e5 --- /dev/null +++ b/MCP/tools/actions/actions_get_repo_variable.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_repo_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/variables/%s", cfg.BaseURL, owner, repo, name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_repo_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_variables_name", + mcp.WithDescription("Get a repository variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_repo_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_reviews_for_run.go b/MCP/tools/actions/actions_get_reviews_for_run.go new file mode 100644 index 0000000..e147b11 --- /dev/null +++ b/MCP/tools/actions/actions_get_reviews_for_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_reviews_for_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/approvals", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_reviews_for_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_approvals", + mcp.WithDescription("Get the review history for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_reviews_for_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_self_hosted_runner_for_org.go b/MCP/tools/actions/actions_get_self_hosted_runner_for_org.go new file mode 100644 index 0000000..5a2c26a --- /dev/null +++ b/MCP/tools/actions/actions_get_self_hosted_runner_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_self_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s", cfg.BaseURL, org, runner_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Runner + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_self_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runners_runner_id", + mcp.WithDescription("Get a self-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_self_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_self_hosted_runner_for_repo.go b/MCP/tools/actions/actions_get_self_hosted_runner_for_repo.go new file mode 100644 index 0000000..fb0a20c --- /dev/null +++ b/MCP/tools/actions/actions_get_self_hosted_runner_for_repo.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_self_hosted_runner_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s", cfg.BaseURL, owner, repo, runner_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Runner + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_self_hosted_runner_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runners_runner_id", + mcp.WithDescription("Get a self-hosted runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_self_hosted_runner_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_self_hosted_runner_group_for_org.go b/MCP/tools/actions/actions_get_self_hosted_runner_group_for_org.go new file mode 100644 index 0000000..d457ac6 --- /dev/null +++ b/MCP/tools/actions/actions_get_self_hosted_runner_group_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_self_hosted_runner_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s", cfg.BaseURL, org, runner_group_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_self_hosted_runner_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runner-groups_runner_group_id", + mcp.WithDescription("Get a self-hosted runner group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_self_hosted_runner_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_workflow.go b/MCP/tools/actions/actions_get_workflow.go new file mode 100644 index 0000000..30b03f8 --- /dev/null +++ b/MCP/tools/actions/actions_get_workflow.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_workflowHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + workflow_idVal, ok := args["workflow_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: workflow_id"), nil + } + workflow_id, ok := workflow_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: workflow_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows/%s", cfg.BaseURL, owner, repo, workflow_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Workflow + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_workflowTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_workflows_workflow_id", + mcp.WithDescription("Get a workflow"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("workflow_id", mcp.Required(), mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_workflowHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_workflow_access_to_repository.go b/MCP/tools/actions/actions_get_workflow_access_to_repository.go new file mode 100644 index 0000000..8285423 --- /dev/null +++ b/MCP/tools/actions/actions_get_workflow_access_to_repository.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_workflow_access_to_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions/access", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_workflow_access_to_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_permissions_access", + mcp.WithDescription("Get the level of access for workflows outside of the repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_workflow_access_to_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_workflow_run.go b/MCP/tools/actions/actions_get_workflow_run.go new file mode 100644 index 0000000..d680e70 --- /dev/null +++ b/MCP/tools/actions/actions_get_workflow_run.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["exclude_pull_requests"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude_pull_requests=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s%s", cfg.BaseURL, owner, repo, run_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id", + mcp.WithDescription("Get a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithBoolean("exclude_pull_requests", mcp.Description("If `true` pull requests are omitted from the response (empty array).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_workflow_run_attempt.go b/MCP/tools/actions/actions_get_workflow_run_attempt.go new file mode 100644 index 0000000..95cd6ad --- /dev/null +++ b/MCP/tools/actions/actions_get_workflow_run_attempt.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_workflow_run_attemptHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + attempt_numberVal, ok := args["attempt_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: attempt_number"), nil + } + attempt_number, ok := attempt_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: attempt_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["exclude_pull_requests"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude_pull_requests=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/attempts/%s%s", cfg.BaseURL, owner, repo, run_id, attempt_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_workflow_run_attemptTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_attempts_attempt_number", + mcp.WithDescription("Get a workflow run attempt"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithNumber("attempt_number", mcp.Required(), mcp.Description("The attempt number of the workflow run.")), + mcp.WithBoolean("exclude_pull_requests", mcp.Description("If `true` pull requests are omitted from the response (empty array).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_workflow_run_attemptHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_workflow_run_usage.go b/MCP/tools/actions/actions_get_workflow_run_usage.go new file mode 100644 index 0000000..8e68605 --- /dev/null +++ b/MCP/tools/actions/actions_get_workflow_run_usage.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_workflow_run_usageHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/timing", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_workflow_run_usageTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_timing", + mcp.WithDescription("Get workflow run usage"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_workflow_run_usageHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_get_workflow_usage.go b/MCP/tools/actions/actions_get_workflow_usage.go new file mode 100644 index 0000000..5c0c0df --- /dev/null +++ b/MCP/tools/actions/actions_get_workflow_usage.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_get_workflow_usageHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + workflow_idVal, ok := args["workflow_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: workflow_id"), nil + } + workflow_id, ok := workflow_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: workflow_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows/%s/timing", cfg.BaseURL, owner, repo, workflow_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_get_workflow_usageTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_workflows_workflow_id_timing", + mcp.WithDescription("Get workflow usage"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("workflow_id", mcp.Required(), mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_get_workflow_usageHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_artifacts_for_repo.go b/MCP/tools/actions/actions_list_artifacts_for_repo.go new file mode 100644 index 0000000..ec024db --- /dev/null +++ b/MCP/tools/actions/actions_list_artifacts_for_repo.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_artifacts_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("name=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/artifacts%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_artifacts_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_artifacts", + mcp.WithDescription("List artifacts for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("name", mcp.Description("The name field of an artifact. When specified, only artifacts with this name will be returned.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_artifacts_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_environment_secrets.go b/MCP/tools/actions/actions_list_environment_secrets.go new file mode 100644 index 0000000..e3225b9 --- /dev/null +++ b/MCP/tools/actions/actions_list_environment_secrets.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_environment_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/secrets%s", cfg.BaseURL, owner, repo, environment_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_environment_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_secrets", + mcp.WithDescription("List environment secrets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_environment_secretsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_environment_variables.go b/MCP/tools/actions/actions_list_environment_variables.go new file mode 100644 index 0000000..94e3f85 --- /dev/null +++ b/MCP/tools/actions/actions_list_environment_variables.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_environment_variablesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/variables%s", cfg.BaseURL, owner, repo, environment_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_environment_variablesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_variables", + mcp.WithDescription("List environment variables"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 30). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_environment_variablesHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_github_hosted_runners_in_group_for_org.go b/MCP/tools/actions/actions_list_github_hosted_runners_in_group_for_org.go new file mode 100644 index 0000000..930454f --- /dev/null +++ b/MCP/tools/actions/actions_list_github_hosted_runners_in_group_for_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_github_hosted_runners_in_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/hosted-runners%s", cfg.BaseURL, org, runner_group_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_github_hosted_runners_in_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runner-groups_runner_group_id_hosted-runners", + mcp.WithDescription("List GitHub-hosted runners in a group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_github_hosted_runners_in_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_hosted_runners_for_org.go b/MCP/tools/actions/actions_list_hosted_runners_for_org.go new file mode 100644 index 0000000..c7cfb78 --- /dev/null +++ b/MCP/tools/actions/actions_list_hosted_runners_for_org.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_hosted_runners_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_hosted_runners_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_hosted-runners", + mcp.WithDescription("List GitHub-hosted runners for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_hosted_runners_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_jobs_for_workflow_run.go b/MCP/tools/actions/actions_list_jobs_for_workflow_run.go new file mode 100644 index 0000000..1cb3105 --- /dev/null +++ b/MCP/tools/actions/actions_list_jobs_for_workflow_run.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_jobs_for_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/jobs%s", cfg.BaseURL, owner, repo, run_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_jobs_for_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_jobs", + mcp.WithDescription("List jobs for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithString("filter", mcp.Description("Filters jobs by their `completed_at` timestamp. `latest` returns jobs from the most recent execution of the workflow run. `all` returns all jobs for a workflow run, including from old executions of the workflow run.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_jobs_for_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_jobs_for_workflow_run_attempt.go b/MCP/tools/actions/actions_list_jobs_for_workflow_run_attempt.go new file mode 100644 index 0000000..ecf25fc --- /dev/null +++ b/MCP/tools/actions/actions_list_jobs_for_workflow_run_attempt.go @@ -0,0 +1,118 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_jobs_for_workflow_run_attemptHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + attempt_numberVal, ok := args["attempt_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: attempt_number"), nil + } + attempt_number, ok := attempt_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: attempt_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/attempts/%s/jobs%s", cfg.BaseURL, owner, repo, run_id, attempt_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_jobs_for_workflow_run_attemptTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_attempts_attempt_number_jobs", + mcp.WithDescription("List jobs for a workflow run attempt"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithNumber("attempt_number", mcp.Required(), mcp.Description("The attempt number of the workflow run.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_jobs_for_workflow_run_attemptHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_org.go b/MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_org.go new file mode 100644 index 0000000..ccf64a5 --- /dev/null +++ b/MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_labels_for_self_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s/labels", cfg.BaseURL, org, runner_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_labels_for_self_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runners_runner_id_labels", + mcp.WithDescription("List labels for a self-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_labels_for_self_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_repo.go b/MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_repo.go new file mode 100644 index 0000000..67caa13 --- /dev/null +++ b/MCP/tools/actions/actions_list_labels_for_self_hosted_runner_for_repo.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_labels_for_self_hosted_runner_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s/labels", cfg.BaseURL, owner, repo, runner_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_labels_for_self_hosted_runner_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runners_runner_id_labels", + mcp.WithDescription("List labels for a self-hosted runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_labels_for_self_hosted_runner_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_org_secrets.go b/MCP/tools/actions/actions_list_org_secrets.go new file mode 100644 index 0000000..4b7250e --- /dev/null +++ b/MCP/tools/actions/actions_list_org_secrets.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_org_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_org_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_secrets", + mcp.WithDescription("List organization secrets"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_org_secretsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_org_variables.go b/MCP/tools/actions/actions_list_org_variables.go new file mode 100644 index 0000000..ab8cbd0 --- /dev/null +++ b/MCP/tools/actions/actions_list_org_variables.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_org_variablesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_org_variablesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_variables", + mcp.WithDescription("List organization variables"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 30). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_org_variablesHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_repo_access_to_self_hosted_runner_group_in_org.go b/MCP/tools/actions/actions_list_repo_access_to_self_hosted_runner_group_in_org.go new file mode 100644 index 0000000..67fc46c --- /dev/null +++ b/MCP/tools/actions/actions_list_repo_access_to_self_hosted_runner_group_in_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/repositories%s", cfg.BaseURL, org, runner_group_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_repo_access_to_self_hosted_runner_group_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runner-groups_runner_group_id_repositories", + mcp.WithDescription("List repository access to a self-hosted runner group in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_repo_organization_secrets.go b/MCP/tools/actions/actions_list_repo_organization_secrets.go new file mode 100644 index 0000000..673dde7 --- /dev/null +++ b/MCP/tools/actions/actions_list_repo_organization_secrets.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_repo_organization_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/organization-secrets%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_repo_organization_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_organization-secrets", + mcp.WithDescription("List repository organization secrets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_repo_organization_secretsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_repo_organization_variables.go b/MCP/tools/actions/actions_list_repo_organization_variables.go new file mode 100644 index 0000000..03b103b --- /dev/null +++ b/MCP/tools/actions/actions_list_repo_organization_variables.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_repo_organization_variablesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/organization-variables%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_repo_organization_variablesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_organization-variables", + mcp.WithDescription("List repository organization variables"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 30). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_repo_organization_variablesHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_repo_secrets.go b/MCP/tools/actions/actions_list_repo_secrets.go new file mode 100644 index 0000000..71e5343 --- /dev/null +++ b/MCP/tools/actions/actions_list_repo_secrets.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_repo_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/secrets%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_repo_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_secrets", + mcp.WithDescription("List repository secrets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_repo_secretsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_repo_variables.go b/MCP/tools/actions/actions_list_repo_variables.go new file mode 100644 index 0000000..488e6b3 --- /dev/null +++ b/MCP/tools/actions/actions_list_repo_variables.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_repo_variablesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/variables%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_repo_variablesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_variables", + mcp.WithDescription("List repository variables"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 30). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_repo_variablesHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_repo_workflows.go b/MCP/tools/actions/actions_list_repo_workflows.go new file mode 100644 index 0000000..38ff7af --- /dev/null +++ b/MCP/tools/actions/actions_list_repo_workflows.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_repo_workflowsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_repo_workflowsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_workflows", + mcp.WithDescription("List repository workflows"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_repo_workflowsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_runner_applications_for_org.go b/MCP/tools/actions/actions_list_runner_applications_for_org.go new file mode 100644 index 0000000..7c7eebd --- /dev/null +++ b/MCP/tools/actions/actions_list_runner_applications_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_runner_applications_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/downloads", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_runner_applications_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runners_downloads", + mcp.WithDescription("List runner applications for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_runner_applications_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_runner_applications_for_repo.go b/MCP/tools/actions/actions_list_runner_applications_for_repo.go new file mode 100644 index 0000000..be094a3 --- /dev/null +++ b/MCP/tools/actions/actions_list_runner_applications_for_repo.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_runner_applications_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/downloads", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_runner_applications_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runners_downloads", + mcp.WithDescription("List runner applications for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_runner_applications_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_selected_repos_for_org_secret.go b/MCP/tools/actions/actions_list_selected_repos_for_org_secret.go new file mode 100644 index 0000000..4330133 --- /dev/null +++ b/MCP/tools/actions/actions_list_selected_repos_for_org_secret.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_selected_repos_for_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s/repositories%s", cfg.BaseURL, org, secret_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_selected_repos_for_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_secrets_secret_name_repositories", + mcp.WithDescription("List selected repositories for an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_selected_repos_for_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_selected_repos_for_org_variable.go b/MCP/tools/actions/actions_list_selected_repos_for_org_variable.go new file mode 100644 index 0000000..06a7b3f --- /dev/null +++ b/MCP/tools/actions/actions_list_selected_repos_for_org_variable.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_selected_repos_for_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s/repositories%s", cfg.BaseURL, org, name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_selected_repos_for_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_variables_name_repositories", + mcp.WithDescription("List selected repositories for an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_selected_repos_for_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_selected_repositories_enabled_github_actions_organization.go b/MCP/tools/actions/actions_list_selected_repositories_enabled_github_actions_organization.go new file mode 100644 index 0000000..b093968 --- /dev/null +++ b/MCP/tools/actions/actions_list_selected_repositories_enabled_github_actions_organization.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_selected_repositories_enabled_github_actions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/repositories%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_selected_repositories_enabled_github_actions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_permissions_repositories", + mcp.WithDescription("List selected repositories enabled for GitHub Actions in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_selected_repositories_enabled_github_actions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_self_hosted_runner_groups_for_org.go b/MCP/tools/actions/actions_list_self_hosted_runner_groups_for_org.go new file mode 100644 index 0000000..1792274 --- /dev/null +++ b/MCP/tools/actions/actions_list_self_hosted_runner_groups_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_self_hosted_runner_groups_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["visible_to_repository"]; ok { + queryParams = append(queryParams, fmt.Sprintf("visible_to_repository=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_self_hosted_runner_groups_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runner-groups", + mcp.WithDescription("List self-hosted runner groups for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("visible_to_repository", mcp.Description("Only return runner groups that are allowed to be used by this repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_self_hosted_runner_groups_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_self_hosted_runners_for_org.go b/MCP/tools/actions/actions_list_self_hosted_runners_for_org.go new file mode 100644 index 0000000..afcdb57 --- /dev/null +++ b/MCP/tools/actions/actions_list_self_hosted_runners_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_self_hosted_runners_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("name=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_self_hosted_runners_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runners", + mcp.WithDescription("List self-hosted runners for an organization"), + mcp.WithString("name", mcp.Description("The name of a self-hosted runner.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_self_hosted_runners_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_self_hosted_runners_for_repo.go b/MCP/tools/actions/actions_list_self_hosted_runners_for_repo.go new file mode 100644 index 0000000..def8035 --- /dev/null +++ b/MCP/tools/actions/actions_list_self_hosted_runners_for_repo.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_self_hosted_runners_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("name=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_self_hosted_runners_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runners", + mcp.WithDescription("List self-hosted runners for a repository"), + mcp.WithString("name", mcp.Description("The name of a self-hosted runner.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_self_hosted_runners_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_self_hosted_runners_in_group_for_org.go b/MCP/tools/actions/actions_list_self_hosted_runners_in_group_for_org.go new file mode 100644 index 0000000..453fbcc --- /dev/null +++ b/MCP/tools/actions/actions_list_self_hosted_runners_in_group_for_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_self_hosted_runners_in_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/runners%s", cfg.BaseURL, org, runner_group_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_self_hosted_runners_in_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_runner-groups_runner_group_id_runners", + mcp.WithDescription("List self-hosted runners in a group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_self_hosted_runners_in_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_workflow_run_artifacts.go b/MCP/tools/actions/actions_list_workflow_run_artifacts.go new file mode 100644 index 0000000..28fefe5 --- /dev/null +++ b/MCP/tools/actions/actions_list_workflow_run_artifacts.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_workflow_run_artifactsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("name=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/artifacts%s", cfg.BaseURL, owner, repo, run_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_workflow_run_artifactsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs_run_id_artifacts", + mcp.WithDescription("List workflow run artifacts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("name", mcp.Description("The name field of an artifact. When specified, only artifacts with this name will be returned.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_workflow_run_artifactsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_workflow_runs.go b/MCP/tools/actions/actions_list_workflow_runs.go new file mode 100644 index 0000000..143be24 --- /dev/null +++ b/MCP/tools/actions/actions_list_workflow_runs.go @@ -0,0 +1,141 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_workflow_runsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + workflow_idVal, ok := args["workflow_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: workflow_id"), nil + } + workflow_id, ok := workflow_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: workflow_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["actor"]; ok { + queryParams = append(queryParams, fmt.Sprintf("actor=%v", val)) + } + if val, ok := args["branch"]; ok { + queryParams = append(queryParams, fmt.Sprintf("branch=%v", val)) + } + if val, ok := args["event"]; ok { + queryParams = append(queryParams, fmt.Sprintf("event=%v", val)) + } + if val, ok := args["status"]; ok { + queryParams = append(queryParams, fmt.Sprintf("status=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["created"]; ok { + queryParams = append(queryParams, fmt.Sprintf("created=%v", val)) + } + if val, ok := args["exclude_pull_requests"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude_pull_requests=%v", val)) + } + if val, ok := args["check_suite_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("check_suite_id=%v", val)) + } + if val, ok := args["head_sha"]; ok { + queryParams = append(queryParams, fmt.Sprintf("head_sha=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/workflows/%s/runs%s", cfg.BaseURL, owner, repo, workflow_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_workflow_runsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_workflows_workflow_id_runs", + mcp.WithDescription("List workflow runs for a workflow"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("workflow_id", mcp.Required(), mcp.Description("The ID of the workflow. You can also pass the workflow file name as a string.")), + mcp.WithString("actor", mcp.Description("Returns someone's workflow runs. Use the login for the user who created the `push` associated with the check suite or workflow run.")), + mcp.WithString("branch", mcp.Description("Returns workflow runs associated with a branch. Use the name of the branch of the `push`.")), + mcp.WithString("event", mcp.Description("Returns workflow run triggered by the event you specify. For example, `push`, `pull_request` or `issue`. For more information, see \"[Events that trigger workflows](https://docs.github.com/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows).\"")), + mcp.WithString("status", mcp.Description("Returns workflow runs with the check run `status` or `conclusion` that you specify. For example, a conclusion can be `success` or a status can be `in_progress`. Only GitHub Actions can set a status of `waiting`, `pending`, or `requested`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("created", mcp.Description("Returns workflow runs created within the given date-time range. For more information on the syntax, see \"[Understanding the search syntax](https://docs.github.com/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates).\"")), + mcp.WithBoolean("exclude_pull_requests", mcp.Description("If `true` pull requests are omitted from the response (empty array).")), + mcp.WithNumber("check_suite_id", mcp.Description("Returns workflow runs with the `check_suite_id` that you specify.")), + mcp.WithString("head_sha", mcp.Description("Only returns workflow runs that are associated with the specified `head_sha`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_workflow_runsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_list_workflow_runs_for_repo.go b/MCP/tools/actions/actions_list_workflow_runs_for_repo.go new file mode 100644 index 0000000..73f7793 --- /dev/null +++ b/MCP/tools/actions/actions_list_workflow_runs_for_repo.go @@ -0,0 +1,132 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_list_workflow_runs_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["actor"]; ok { + queryParams = append(queryParams, fmt.Sprintf("actor=%v", val)) + } + if val, ok := args["branch"]; ok { + queryParams = append(queryParams, fmt.Sprintf("branch=%v", val)) + } + if val, ok := args["event"]; ok { + queryParams = append(queryParams, fmt.Sprintf("event=%v", val)) + } + if val, ok := args["status"]; ok { + queryParams = append(queryParams, fmt.Sprintf("status=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["created"]; ok { + queryParams = append(queryParams, fmt.Sprintf("created=%v", val)) + } + if val, ok := args["exclude_pull_requests"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude_pull_requests=%v", val)) + } + if val, ok := args["check_suite_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("check_suite_id=%v", val)) + } + if val, ok := args["head_sha"]; ok { + queryParams = append(queryParams, fmt.Sprintf("head_sha=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_list_workflow_runs_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_actions_runs", + mcp.WithDescription("List workflow runs for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("actor", mcp.Description("Returns someone's workflow runs. Use the login for the user who created the `push` associated with the check suite or workflow run.")), + mcp.WithString("branch", mcp.Description("Returns workflow runs associated with a branch. Use the name of the branch of the `push`.")), + mcp.WithString("event", mcp.Description("Returns workflow run triggered by the event you specify. For example, `push`, `pull_request` or `issue`. For more information, see \"[Events that trigger workflows](https://docs.github.com/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows).\"")), + mcp.WithString("status", mcp.Description("Returns workflow runs with the check run `status` or `conclusion` that you specify. For example, a conclusion can be `success` or a status can be `in_progress`. Only GitHub Actions can set a status of `waiting`, `pending`, or `requested`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("created", mcp.Description("Returns workflow runs created within the given date-time range. For more information on the syntax, see \"[Understanding the search syntax](https://docs.github.com/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates).\"")), + mcp.WithBoolean("exclude_pull_requests", mcp.Description("If `true` pull requests are omitted from the response (empty array).")), + mcp.WithNumber("check_suite_id", mcp.Description("Returns workflow runs with the `check_suite_id` that you specify.")), + mcp.WithString("head_sha", mcp.Description("Only returns workflow runs that are associated with the specified `head_sha`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_list_workflow_runs_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_re_run_job_for_workflow_run.go b/MCP/tools/actions/actions_re_run_job_for_workflow_run.go new file mode 100644 index 0000000..0efdb14 --- /dev/null +++ b/MCP/tools/actions/actions_re_run_job_for_workflow_run.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_re_run_job_for_workflow_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + job_idVal, ok := args["job_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: job_id"), nil + } + job_id, ok := job_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: job_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/jobs/%s/rerun", cfg.BaseURL, owner, repo, job_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_re_run_job_for_workflow_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_jobs_job_id_rerun", + mcp.WithDescription("Re-run a job from a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("job_id", mcp.Required(), mcp.Description("The unique identifier of the job.")), + mcp.WithBoolean("enable_debug_logging", mcp.Description("Input parameter: Whether to enable debug logging for the re-run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_re_run_job_for_workflow_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_re_run_workflow.go b/MCP/tools/actions/actions_re_run_workflow.go new file mode 100644 index 0000000..7f4c7fb --- /dev/null +++ b/MCP/tools/actions/actions_re_run_workflow.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_re_run_workflowHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/rerun", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_re_run_workflowTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_rerun", + mcp.WithDescription("Re-run a workflow"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithBoolean("enable_debug_logging", mcp.Description("Input parameter: Whether to enable debug logging for the re-run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_re_run_workflowHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_re_run_workflow_failed_jobs.go b/MCP/tools/actions/actions_re_run_workflow_failed_jobs.go new file mode 100644 index 0000000..7815943 --- /dev/null +++ b/MCP/tools/actions/actions_re_run_workflow_failed_jobs.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_re_run_workflow_failed_jobsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/rerun-failed-jobs", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_re_run_workflow_failed_jobsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_rerun-failed-jobs", + mcp.WithDescription("Re-run failed jobs from a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithBoolean("enable_debug_logging", mcp.Description("Input parameter: Whether to enable debug logging for the re-run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_re_run_workflow_failed_jobsHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_org.go b/MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_org.go new file mode 100644 index 0000000..795115e --- /dev/null +++ b/MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_all_custom_labels_from_self_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s/labels", cfg.BaseURL, org, runner_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_all_custom_labels_from_self_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_runners_runner_id_labels", + mcp.WithDescription("Remove all custom labels from a self-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_all_custom_labels_from_self_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_repo.go b/MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_repo.go new file mode 100644 index 0000000..692c60a --- /dev/null +++ b/MCP/tools/actions/actions_remove_all_custom_labels_from_self_hosted_runner_for_repo.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_all_custom_labels_from_self_hosted_runner_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s/labels", cfg.BaseURL, owner, repo, runner_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_all_custom_labels_from_self_hosted_runner_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_runners_runner_id_labels", + mcp.WithDescription("Remove all custom labels from a self-hosted runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_all_custom_labels_from_self_hosted_runner_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_org.go b/MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_org.go new file mode 100644 index 0000000..40e3ab8 --- /dev/null +++ b/MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_custom_label_from_self_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s/labels/%s", cfg.BaseURL, org, runner_id, name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_custom_label_from_self_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_runners_runner_id_labels_name", + mcp.WithDescription("Remove a custom label from a self-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of a self-hosted runner's custom label.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_custom_label_from_self_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_repo.go b/MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_repo.go new file mode 100644 index 0000000..678bbeb --- /dev/null +++ b/MCP/tools/actions/actions_remove_custom_label_from_self_hosted_runner_for_repo.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_custom_label_from_self_hosted_runner_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s/labels/%s", cfg.BaseURL, owner, repo, runner_id, name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_custom_label_from_self_hosted_runner_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_actions_runners_runner_id_labels_name", + mcp.WithDescription("Remove a custom label from a self-hosted runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of a self-hosted runner's custom label.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_custom_label_from_self_hosted_runner_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_repo_access_to_self_hosted_runner_group_in_org.go b/MCP/tools/actions/actions_remove_repo_access_to_self_hosted_runner_group_in_org.go new file mode 100644 index 0000000..840a883 --- /dev/null +++ b/MCP/tools/actions/actions_remove_repo_access_to_self_hosted_runner_group_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/repositories/%s", cfg.BaseURL, org, runner_group_id, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_repo_access_to_self_hosted_runner_group_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_runner-groups_runner_group_id_repositories_repository_id", + mcp.WithDescription("Remove repository access to a self-hosted runner group in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The unique identifier of the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_selected_repo_from_org_secret.go b/MCP/tools/actions/actions_remove_selected_repo_from_org_secret.go new file mode 100644 index 0000000..61d27bc --- /dev/null +++ b/MCP/tools/actions/actions_remove_selected_repo_from_org_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_selected_repo_from_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s/repositories/%s", cfg.BaseURL, org, secret_name, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_selected_repo_from_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Remove selected repository from an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_selected_repo_from_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_selected_repo_from_org_variable.go b/MCP/tools/actions/actions_remove_selected_repo_from_org_variable.go new file mode 100644 index 0000000..0f65173 --- /dev/null +++ b/MCP/tools/actions/actions_remove_selected_repo_from_org_variable.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_selected_repo_from_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s/repositories/%s", cfg.BaseURL, org, name, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_selected_repo_from_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_variables_name_repositories_repository_id", + mcp.WithDescription("Remove selected repository from an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_selected_repo_from_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_remove_self_hosted_runner_from_group_for_org.go b/MCP/tools/actions/actions_remove_self_hosted_runner_from_group_for_org.go new file mode 100644 index 0000000..8981ec9 --- /dev/null +++ b/MCP/tools/actions/actions_remove_self_hosted_runner_from_group_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_remove_self_hosted_runner_from_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/runners/%s", cfg.BaseURL, org, runner_group_id, runner_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_remove_self_hosted_runner_from_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_actions_runner-groups_runner_group_id_runners_runner_id", + mcp.WithDescription("Remove a self-hosted runner from a group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_remove_self_hosted_runner_from_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_review_custom_gates_for_run.go b/MCP/tools/actions/actions_review_custom_gates_for_run.go new file mode 100644 index 0000000..30d2aa2 --- /dev/null +++ b/MCP/tools/actions/actions_review_custom_gates_for_run.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_review_custom_gates_for_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/deployment_protection_rule", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_review_custom_gates_for_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_deployment_protection_rule", + mcp.WithDescription("Review custom deployment protection rules for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_review_custom_gates_for_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_review_pending_deployments_for_run.go b/MCP/tools/actions/actions_review_pending_deployments_for_run.go new file mode 100644 index 0000000..8147079 --- /dev/null +++ b/MCP/tools/actions/actions_review_pending_deployments_for_run.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_review_pending_deployments_for_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + run_idVal, ok := args["run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: run_id"), nil + } + run_id, ok := run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: run_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runs/%s/pending_deployments", cfg.BaseURL, owner, repo, run_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Deployment + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_review_pending_deployments_for_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_actions_runs_run_id_pending_deployments", + mcp.WithDescription("Review pending deployments for a workflow run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("run_id", mcp.Required(), mcp.Description("The unique identifier of the workflow run.")), + mcp.WithArray("environment_ids", mcp.Required(), mcp.Description("Input parameter: The list of environment ids to approve or reject")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: Whether to approve or reject deployment to the specified environments.")), + mcp.WithString("comment", mcp.Required(), mcp.Description("Input parameter: A comment to accompany the deployment review")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_review_pending_deployments_for_runHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_allowed_actions_organization.go b/MCP/tools/actions/actions_set_allowed_actions_organization.go new file mode 100644 index 0000000..645677d --- /dev/null +++ b/MCP/tools/actions/actions_set_allowed_actions_organization.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_allowed_actions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/selected-actions", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_allowed_actions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_permissions_selected-actions", + mcp.WithDescription("Set allowed actions and reusable workflows for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithBoolean("github_owned_allowed", mcp.Description("Input parameter: Whether GitHub-owned actions are allowed. For example, this includes the actions in the `actions` organization.")), + mcp.WithArray("patterns_allowed", mcp.Description("Input parameter: Specifies a list of string-matching patterns to allow specific action(s) and reusable workflow(s). Wildcards, tags, and SHAs are allowed. For example, `monalisa/octocat@*`, `monalisa/octocat@v2`, `monalisa/*`.\n\n> [!NOTE]\n> The `patterns_allowed` setting only applies to public repositories.")), + mcp.WithBoolean("verified_allowed", mcp.Description("Input parameter: Whether actions from GitHub Marketplace verified creators are allowed. Set to `true` to allow all actions by GitHub Marketplace verified creators.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_allowed_actions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_allowed_actions_repository.go b/MCP/tools/actions/actions_set_allowed_actions_repository.go new file mode 100644 index 0000000..db4687c --- /dev/null +++ b/MCP/tools/actions/actions_set_allowed_actions_repository.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_allowed_actions_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions/selected-actions", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_allowed_actions_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_permissions_selected-actions", + mcp.WithDescription("Set allowed actions and reusable workflows for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("verified_allowed", mcp.Description("Input parameter: Whether actions from GitHub Marketplace verified creators are allowed. Set to `true` to allow all actions by GitHub Marketplace verified creators.")), + mcp.WithBoolean("github_owned_allowed", mcp.Description("Input parameter: Whether GitHub-owned actions are allowed. For example, this includes the actions in the `actions` organization.")), + mcp.WithArray("patterns_allowed", mcp.Description("Input parameter: Specifies a list of string-matching patterns to allow specific action(s) and reusable workflow(s). Wildcards, tags, and SHAs are allowed. For example, `monalisa/octocat@*`, `monalisa/octocat@v2`, `monalisa/*`.\n\n> [!NOTE]\n> The `patterns_allowed` setting only applies to public repositories.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_allowed_actions_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_org.go b/MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_org.go new file mode 100644 index 0000000..243a767 --- /dev/null +++ b/MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_org.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_custom_labels_for_self_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runners/%s/labels", cfg.BaseURL, org, runner_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_custom_labels_for_self_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_runners_runner_id_labels", + mcp.WithDescription("Set custom labels for a self-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + mcp.WithArray("labels", mcp.Required(), mcp.Description("Input parameter: The names of the custom labels to set for the runner. You can pass an empty array to remove all custom labels.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_custom_labels_for_self_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_repo.go b/MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_repo.go new file mode 100644 index 0000000..c0c560f --- /dev/null +++ b/MCP/tools/actions/actions_set_custom_labels_for_self_hosted_runner_for_repo.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_custom_labels_for_self_hosted_runner_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + runner_idVal, ok := args["runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_id"), nil + } + runner_id, ok := runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/runners/%s/labels", cfg.BaseURL, owner, repo, runner_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_custom_labels_for_self_hosted_runner_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_runners_runner_id_labels", + mcp.WithDescription("Set custom labels for a self-hosted runner for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("runner_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner.")), + mcp.WithArray("labels", mcp.Required(), mcp.Description("Input parameter: The names of the custom labels to set for the runner. You can pass an empty array to remove all custom labels.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_custom_labels_for_self_hosted_runner_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_custom_oidc_sub_claim_for_repo.go b/MCP/tools/actions/actions_set_custom_oidc_sub_claim_for_repo.go new file mode 100644 index 0000000..2913d78 --- /dev/null +++ b/MCP/tools/actions/actions_set_custom_oidc_sub_claim_for_repo.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_custom_oidc_sub_claim_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/oidc/customization/sub", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_custom_oidc_sub_claim_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_oidc_customization_sub", + mcp.WithDescription("Set the customization template for an OIDC subject claim for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("use_default", mcp.Required(), mcp.Description("Input parameter: Whether to use the default template or not. If `true`, the `include_claim_keys` field is ignored.")), + mcp.WithArray("include_claim_keys", mcp.Description("Input parameter: Array of unique strings. Each claim key can only contain alphanumeric characters and underscores.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_custom_oidc_sub_claim_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_organization.go b/MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_organization.go new file mode 100644 index 0000000..b9cff86 --- /dev/null +++ b/MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_organization.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_github_actions_default_workflow_permissions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/workflow", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_github_actions_default_workflow_permissions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_permissions_workflow", + mcp.WithDescription("Set default workflow permissions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithBoolean("can_approve_pull_request_reviews", mcp.Description("Input parameter: Whether GitHub Actions can approve pull requests. Enabling this can be a security risk.")), + mcp.WithString("default_workflow_permissions", mcp.Description("Input parameter: The default workflow permissions granted to the GITHUB_TOKEN when running workflows.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_github_actions_default_workflow_permissions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_repository.go b/MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_repository.go new file mode 100644 index 0000000..02ada2a --- /dev/null +++ b/MCP/tools/actions/actions_set_github_actions_default_workflow_permissions_repository.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_github_actions_default_workflow_permissions_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions/workflow", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_github_actions_default_workflow_permissions_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_permissions_workflow", + mcp.WithDescription("Set default workflow permissions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("default_workflow_permissions", mcp.Description("Input parameter: The default workflow permissions granted to the GITHUB_TOKEN when running workflows.")), + mcp.WithBoolean("can_approve_pull_request_reviews", mcp.Description("Input parameter: Whether GitHub Actions can approve pull requests. Enabling this can be a security risk.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_github_actions_default_workflow_permissions_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_github_actions_permissions_organization.go b/MCP/tools/actions/actions_set_github_actions_permissions_organization.go new file mode 100644 index 0000000..353e411 --- /dev/null +++ b/MCP/tools/actions/actions_set_github_actions_permissions_organization.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_github_actions_permissions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_github_actions_permissions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_permissions", + mcp.WithDescription("Set GitHub Actions permissions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("allowed_actions", mcp.Description("Input parameter: The permissions policy that controls the actions and reusable workflows that are allowed to run.")), + mcp.WithString("enabled_repositories", mcp.Required(), mcp.Description("Input parameter: The policy that controls the repositories in the organization that are allowed to run GitHub Actions.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_github_actions_permissions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_github_actions_permissions_repository.go b/MCP/tools/actions/actions_set_github_actions_permissions_repository.go new file mode 100644 index 0000000..74dfc52 --- /dev/null +++ b/MCP/tools/actions/actions_set_github_actions_permissions_repository.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_github_actions_permissions_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_github_actions_permissions_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_permissions", + mcp.WithDescription("Set GitHub Actions permissions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("allowed_actions", mcp.Description("Input parameter: The permissions policy that controls the actions and reusable workflows that are allowed to run.")), + mcp.WithBoolean("enabled", mcp.Required(), mcp.Description("Input parameter: Whether GitHub Actions is enabled on the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_github_actions_permissions_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_repo_access_to_self_hosted_runner_group_in_org.go b/MCP/tools/actions/actions_set_repo_access_to_self_hosted_runner_group_in_org.go new file mode 100644 index 0000000..4d6e021 --- /dev/null +++ b/MCP/tools/actions/actions_set_repo_access_to_self_hosted_runner_group_in_org.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/repositories", cfg.BaseURL, org, runner_group_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_repo_access_to_self_hosted_runner_group_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_runner-groups_runner_group_id_repositories", + mcp.WithDescription("Set repository access for a self-hosted runner group in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: List of repository IDs that can access the runner group.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_repo_access_to_self_hosted_runner_group_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_selected_repos_for_org_secret.go b/MCP/tools/actions/actions_set_selected_repos_for_org_secret.go new file mode 100644 index 0000000..5aedc46 --- /dev/null +++ b/MCP/tools/actions/actions_set_selected_repos_for_org_secret.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_selected_repos_for_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/secrets/%s/repositories", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_selected_repos_for_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_secrets_secret_name_repositories", + mcp.WithDescription("Set selected repositories for an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: An array of repository ids that can access the organization secret. You can only provide a list of repository ids when the `visibility` is set to `selected`. You can add and remove individual repositories using the [Add selected repository to an organization secret](https://docs.github.com/rest/actions/secrets#add-selected-repository-to-an-organization-secret) and [Remove selected repository from an organization secret](https://docs.github.com/rest/actions/secrets#remove-selected-repository-from-an-organization-secret) endpoints.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_selected_repos_for_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_selected_repos_for_org_variable.go b/MCP/tools/actions/actions_set_selected_repos_for_org_variable.go new file mode 100644 index 0000000..2a299a1 --- /dev/null +++ b/MCP/tools/actions/actions_set_selected_repos_for_org_variable.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_selected_repos_for_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s/repositories", cfg.BaseURL, org, name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_selected_repos_for_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_variables_name_repositories", + mcp.WithDescription("Set selected repositories for an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: The IDs of the repositories that can access the organization variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_selected_repos_for_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_selected_repositories_enabled_github_actions_organization.go b/MCP/tools/actions/actions_set_selected_repositories_enabled_github_actions_organization.go new file mode 100644 index 0000000..ca76b78 --- /dev/null +++ b/MCP/tools/actions/actions_set_selected_repositories_enabled_github_actions_organization.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_selected_repositories_enabled_github_actions_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/permissions/repositories", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_selected_repositories_enabled_github_actions_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_permissions_repositories", + mcp.WithDescription("Set selected repositories enabled for GitHub Actions in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: List of repository IDs to enable for GitHub Actions.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_selected_repositories_enabled_github_actions_organizationHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_self_hosted_runners_in_group_for_org.go b/MCP/tools/actions/actions_set_self_hosted_runners_in_group_for_org.go new file mode 100644 index 0000000..d89b254 --- /dev/null +++ b/MCP/tools/actions/actions_set_self_hosted_runners_in_group_for_org.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_self_hosted_runners_in_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s/runners", cfg.BaseURL, org, runner_group_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_self_hosted_runners_in_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_runner-groups_runner_group_id_runners", + mcp.WithDescription("Set self-hosted runners in a group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithArray("runners", mcp.Required(), mcp.Description("Input parameter: List of runner IDs to add to the runner group.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_self_hosted_runners_in_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_set_workflow_access_to_repository.go b/MCP/tools/actions/actions_set_workflow_access_to_repository.go new file mode 100644 index 0000000..6b6a1d1 --- /dev/null +++ b/MCP/tools/actions/actions_set_workflow_access_to_repository.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_set_workflow_access_to_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/permissions/access", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_set_workflow_access_to_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_actions_permissions_access", + mcp.WithDescription("Set the level of access for workflows outside of the repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("access_level", mcp.Required(), mcp.Description("Input parameter: Defines the level of access that workflows outside of the repository have to actions and reusable workflows within the\nrepository.\n\n`none` means the access is only possible from workflows in this repository. `user` level access allows sharing across user owned private repositories only. `organization` level access allows sharing across the organization.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_set_workflow_access_to_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_update_environment_variable.go b/MCP/tools/actions/actions_update_environment_variable.go new file mode 100644 index 0000000..065e4f0 --- /dev/null +++ b/MCP/tools/actions/actions_update_environment_variable.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_update_environment_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/variables/%s", cfg.BaseURL, owner, repo, name, environment_name) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_update_environment_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_environments_environment_name_variables_name", + mcp.WithDescription("Update an environment variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the variable.")), + mcp.WithString("value", mcp.Description("Input parameter: The value of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_update_environment_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_update_hosted_runner_for_org.go b/MCP/tools/actions/actions_update_hosted_runner_for_org.go new file mode 100644 index 0000000..e735416 --- /dev/null +++ b/MCP/tools/actions/actions_update_hosted_runner_for_org.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_update_hosted_runner_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hosted_runner_idVal, ok := args["hosted_runner_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hosted_runner_id"), nil + } + hosted_runner_id, ok := hosted_runner_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hosted_runner_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/hosted-runners/%s", cfg.BaseURL, org, hosted_runner_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_update_hosted_runner_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_actions_hosted-runners_hosted_runner_id", + mcp.WithDescription("Update a GitHub-hosted runner for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hosted_runner_id", mcp.Required(), mcp.Description("Unique identifier of the GitHub-hosted runner.")), + mcp.WithBoolean("enable_static_ip", mcp.Description("Input parameter: Whether this runner should be updated with a static public IP. Note limit on account. To list limits on account, use `GET actions/hosted-runners/limits`")), + mcp.WithNumber("maximum_runners", mcp.Description("Input parameter: The maximum amount of runners to scale up to. Runners will not auto-scale above this number. Use this setting to limit your cost.")), + mcp.WithString("name", mcp.Description("Input parameter: Name of the runner. Must be between 1 and 64 characters and may only contain upper and lowercase letters a-z, numbers 0-9, '.', '-', and '_'.")), + mcp.WithNumber("runner_group_id", mcp.Description("Input parameter: The existing runner group to add this runner to.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_update_hosted_runner_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_update_org_variable.go b/MCP/tools/actions/actions_update_org_variable.go new file mode 100644 index 0000000..65564a6 --- /dev/null +++ b/MCP/tools/actions/actions_update_org_variable.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_update_org_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/variables/%s", cfg.BaseURL, org, name) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_update_org_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_actions_variables_name", + mcp.WithDescription("Update an organization variable"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the variable.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository ids that can access the organization variable. You can only provide a list of repository ids when the `visibility` is set to `selected`.")), + mcp.WithString("value", mcp.Description("Input parameter: The value of the variable.")), + mcp.WithString("visibility", mcp.Description("Input parameter: The type of repositories in the organization that can access the variable. `selected` means only the repositories specified by `selected_repository_ids` can access the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_update_org_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_update_repo_variable.go b/MCP/tools/actions/actions_update_repo_variable.go new file mode 100644 index 0000000..695129b --- /dev/null +++ b/MCP/tools/actions/actions_update_repo_variable.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_update_repo_variableHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/actions/variables/%s", cfg.BaseURL, owner, repo, name) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_update_repo_variableTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_actions_variables_name", + mcp.WithDescription("Update a repository variable"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("The name of the variable.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the variable.")), + mcp.WithString("value", mcp.Description("Input parameter: The value of the variable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_update_repo_variableHandler(cfg), + } +} diff --git a/MCP/tools/actions/actions_update_self_hosted_runner_group_for_org.go b/MCP/tools/actions/actions_update_self_hosted_runner_group_for_org.go new file mode 100644 index 0000000..dd58294 --- /dev/null +++ b/MCP/tools/actions/actions_update_self_hosted_runner_group_for_org.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Actions_update_self_hosted_runner_group_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + runner_group_idVal, ok := args["runner_group_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: runner_group_id"), nil + } + runner_group_id, ok := runner_group_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: runner_group_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/runner-groups/%s", cfg.BaseURL, org, runner_group_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActions_update_self_hosted_runner_group_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_actions_runner-groups_runner_group_id", + mcp.WithDescription("Update a self-hosted runner group for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("runner_group_id", mcp.Required(), mcp.Description("Unique identifier of the self-hosted runner group.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the runner group.")), + mcp.WithString("network_configuration_id", mcp.Description("Input parameter: The identifier of a hosted compute network configuration.")), + mcp.WithBoolean("restricted_to_workflows", mcp.Description("Input parameter: If `true`, the runner group will be restricted to running only the workflows specified in the `selected_workflows` array.")), + mcp.WithArray("selected_workflows", mcp.Description("Input parameter: List of workflows the runner group should be allowed to run. This setting will be ignored unless `restricted_to_workflows` is set to `true`.")), + mcp.WithString("visibility", mcp.Description("Input parameter: Visibility of a runner group. You can select all repositories, select individual repositories, or all private repositories.")), + mcp.WithBoolean("allows_public_repositories", mcp.Description("Input parameter: Whether the runner group can be used by `public` repositories.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Actions_update_self_hosted_runner_group_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_check_repo_is_starred_by_authenticated_user.go b/MCP/tools/activity/activity_check_repo_is_starred_by_authenticated_user.go new file mode 100644 index 0000000..33dfd20 --- /dev/null +++ b/MCP/tools/activity/activity_check_repo_is_starred_by_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_check_repo_is_starred_by_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/user/starred/%s/%s", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_check_repo_is_starred_by_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_starred_owner_repo", + mcp.WithDescription("Check if a repository is starred by the authenticated user"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_check_repo_is_starred_by_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_delete_repo_subscription.go b/MCP/tools/activity/activity_delete_repo_subscription.go new file mode 100644 index 0000000..5358e2a --- /dev/null +++ b/MCP/tools/activity/activity_delete_repo_subscription.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_delete_repo_subscriptionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/subscription", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_delete_repo_subscriptionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_subscription", + mcp.WithDescription("Delete a repository subscription"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_delete_repo_subscriptionHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_delete_thread_subscription.go b/MCP/tools/activity/activity_delete_thread_subscription.go new file mode 100644 index 0000000..21705e8 --- /dev/null +++ b/MCP/tools/activity/activity_delete_thread_subscription.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_delete_thread_subscriptionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + thread_idVal, ok := args["thread_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: thread_id"), nil + } + thread_id, ok := thread_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: thread_id"), nil + } + url := fmt.Sprintf("%s/notifications/threads/%s/subscription", cfg.BaseURL, thread_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_delete_thread_subscriptionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_notifications_threads_thread_id_subscription", + mcp.WithDescription("Delete a thread subscription"), + mcp.WithNumber("thread_id", mcp.Required(), mcp.Description("The unique identifier of the notification thread. This corresponds to the value returned in the `id` field when you retrieve notifications (for example with the [`GET /notifications` operation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_delete_thread_subscriptionHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_get_feeds.go b/MCP/tools/activity/activity_get_feeds.go new file mode 100644 index 0000000..3e377ed --- /dev/null +++ b/MCP/tools/activity/activity_get_feeds.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_get_feedsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/feeds", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Feed + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_get_feedsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_feeds", + mcp.WithDescription("Get feeds"), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_get_feedsHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_get_repo_subscription.go b/MCP/tools/activity/activity_get_repo_subscription.go new file mode 100644 index 0000000..2e74fd0 --- /dev/null +++ b/MCP/tools/activity/activity_get_repo_subscription.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_get_repo_subscriptionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/subscription", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_get_repo_subscriptionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_subscription", + mcp.WithDescription("Get a repository subscription"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_get_repo_subscriptionHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_get_thread.go b/MCP/tools/activity/activity_get_thread.go new file mode 100644 index 0000000..2bd9fc9 --- /dev/null +++ b/MCP/tools/activity/activity_get_thread.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_get_threadHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + thread_idVal, ok := args["thread_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: thread_id"), nil + } + thread_id, ok := thread_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: thread_id"), nil + } + url := fmt.Sprintf("%s/notifications/threads/%s", cfg.BaseURL, thread_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Thread + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_get_threadTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_notifications_threads_thread_id", + mcp.WithDescription("Get a thread"), + mcp.WithNumber("thread_id", mcp.Required(), mcp.Description("The unique identifier of the notification thread. This corresponds to the value returned in the `id` field when you retrieve notifications (for example with the [`GET /notifications` operation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_get_threadHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_get_thread_subscription_for_authenticated_user.go b/MCP/tools/activity/activity_get_thread_subscription_for_authenticated_user.go new file mode 100644 index 0000000..744a574 --- /dev/null +++ b/MCP/tools/activity/activity_get_thread_subscription_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_get_thread_subscription_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + thread_idVal, ok := args["thread_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: thread_id"), nil + } + thread_id, ok := thread_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: thread_id"), nil + } + url := fmt.Sprintf("%s/notifications/threads/%s/subscription", cfg.BaseURL, thread_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_get_thread_subscription_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_notifications_threads_thread_id_subscription", + mcp.WithDescription("Get a thread subscription for the authenticated user"), + mcp.WithNumber("thread_id", mcp.Required(), mcp.Description("The unique identifier of the notification thread. This corresponds to the value returned in the `id` field when you retrieve notifications (for example with the [`GET /notifications` operation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_get_thread_subscription_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_events_for_authenticated_user.go b/MCP/tools/activity/activity_list_events_for_authenticated_user.go new file mode 100644 index 0000000..86fef70 --- /dev/null +++ b/MCP/tools/activity/activity_list_events_for_authenticated_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_events_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/events%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_events_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_events", + mcp.WithDescription("List events for the authenticated user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_events_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_notifications_for_authenticated_user.go b/MCP/tools/activity/activity_list_notifications_for_authenticated_user.go new file mode 100644 index 0000000..e4b6bb2 --- /dev/null +++ b/MCP/tools/activity/activity_list_notifications_for_authenticated_user.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_notifications_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["all"]; ok { + queryParams = append(queryParams, fmt.Sprintf("all=%v", val)) + } + if val, ok := args["participating"]; ok { + queryParams = append(queryParams, fmt.Sprintf("participating=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/notifications%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Thread + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_notifications_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_notifications", + mcp.WithDescription("List notifications for the authenticated user"), + mcp.WithBoolean("all", mcp.Description("If `true`, show notifications marked as read.")), + mcp.WithBoolean("participating", mcp.Description("If `true`, only shows notifications in which the user is directly participating or mentioned.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("before", mcp.Description("Only show notifications updated before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 50). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_notifications_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_org_events_for_authenticated_user.go b/MCP/tools/activity/activity_list_org_events_for_authenticated_user.go new file mode 100644 index 0000000..2dd0060 --- /dev/null +++ b/MCP/tools/activity/activity_list_org_events_for_authenticated_user.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_org_events_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/events/orgs/%s%s", cfg.BaseURL, username, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_org_events_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_events_orgs_org", + mcp.WithDescription("List organization events for the authenticated user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_org_events_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_public_events.go b/MCP/tools/activity/activity_list_public_events.go new file mode 100644 index 0000000..aa37216 --- /dev/null +++ b/MCP/tools/activity/activity_list_public_events.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_public_eventsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/events%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_public_eventsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_events", + mcp.WithDescription("List public events"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_public_eventsHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_public_events_for_repo_network.go b/MCP/tools/activity/activity_list_public_events_for_repo_network.go new file mode 100644 index 0000000..7626dac --- /dev/null +++ b/MCP/tools/activity/activity_list_public_events_for_repo_network.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_public_events_for_repo_networkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/networks/%s/%s/events%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_public_events_for_repo_networkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_networks_owner_repo_events", + mcp.WithDescription("List public events for a network of repositories"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_public_events_for_repo_networkHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_public_events_for_user.go b/MCP/tools/activity/activity_list_public_events_for_user.go new file mode 100644 index 0000000..6e93be6 --- /dev/null +++ b/MCP/tools/activity/activity_list_public_events_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_public_events_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/events/public%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_public_events_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_events_public", + mcp.WithDescription("List public events for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_public_events_for_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_public_org_events.go b/MCP/tools/activity/activity_list_public_org_events.go new file mode 100644 index 0000000..8dfb37e --- /dev/null +++ b/MCP/tools/activity/activity_list_public_org_events.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_public_org_eventsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/events%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_public_org_eventsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_events", + mcp.WithDescription("List public organization events"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_public_org_eventsHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_received_events_for_user.go b/MCP/tools/activity/activity_list_received_events_for_user.go new file mode 100644 index 0000000..e62d249 --- /dev/null +++ b/MCP/tools/activity/activity_list_received_events_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_received_events_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/received_events%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_received_events_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_received_events", + mcp.WithDescription("List events received by the authenticated user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_received_events_for_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_received_public_events_for_user.go b/MCP/tools/activity/activity_list_received_public_events_for_user.go new file mode 100644 index 0000000..be5173b --- /dev/null +++ b/MCP/tools/activity/activity_list_received_public_events_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_received_public_events_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/received_events/public%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_received_public_events_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_received_events_public", + mcp.WithDescription("List public events received by a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_received_public_events_for_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_repo_events.go b/MCP/tools/activity/activity_list_repo_events.go new file mode 100644 index 0000000..f2bb408 --- /dev/null +++ b/MCP/tools/activity/activity_list_repo_events.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_repo_eventsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/events%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Event + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_repo_eventsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_events", + mcp.WithDescription("List repository events"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_repo_eventsHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_repo_notifications_for_authenticated_user.go b/MCP/tools/activity/activity_list_repo_notifications_for_authenticated_user.go new file mode 100644 index 0000000..005ad58 --- /dev/null +++ b/MCP/tools/activity/activity_list_repo_notifications_for_authenticated_user.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_repo_notifications_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["all"]; ok { + queryParams = append(queryParams, fmt.Sprintf("all=%v", val)) + } + if val, ok := args["participating"]; ok { + queryParams = append(queryParams, fmt.Sprintf("participating=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/notifications%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Thread + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_repo_notifications_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_notifications", + mcp.WithDescription("List repository notifications for the authenticated user"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("all", mcp.Description("If `true`, show notifications marked as read.")), + mcp.WithBoolean("participating", mcp.Description("If `true`, only shows notifications in which the user is directly participating or mentioned.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("before", mcp.Description("Only show notifications updated before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_repo_notifications_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_repos_starred_by_authenticated_user.go b/MCP/tools/activity/activity_list_repos_starred_by_authenticated_user.go new file mode 100644 index 0000000..5bc229e --- /dev/null +++ b/MCP/tools/activity/activity_list_repos_starred_by_authenticated_user.go @@ -0,0 +1,90 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_repos_starred_by_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/starred%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Repository + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_repos_starred_by_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_starred", + mcp.WithDescription("List repositories starred by the authenticated user"), + mcp.WithString("sort", mcp.Description("The property to sort the results by. `created` means when the repository was starred. `updated` means when the repository was last pushed to.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_repos_starred_by_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_repos_starred_by_user.go b/MCP/tools/activity/activity_list_repos_starred_by_user.go new file mode 100644 index 0000000..3b53972 --- /dev/null +++ b/MCP/tools/activity/activity_list_repos_starred_by_user.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_repos_starred_by_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/starred%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_repos_starred_by_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_starred", + mcp.WithDescription("List repositories starred by a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by. `created` means when the repository was starred. `updated` means when the repository was last pushed to.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_repos_starred_by_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_repos_watched_by_user.go b/MCP/tools/activity/activity_list_repos_watched_by_user.go new file mode 100644 index 0000000..d3e98fd --- /dev/null +++ b/MCP/tools/activity/activity_list_repos_watched_by_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_repos_watched_by_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/subscriptions%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_repos_watched_by_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_subscriptions", + mcp.WithDescription("List repositories watched by a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_repos_watched_by_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_stargazers_for_repo.go b/MCP/tools/activity/activity_list_stargazers_for_repo.go new file mode 100644 index 0000000..12010dd --- /dev/null +++ b/MCP/tools/activity/activity_list_stargazers_for_repo.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_stargazers_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/stargazers%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_stargazers_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_stargazers", + mcp.WithDescription("List stargazers"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_stargazers_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_watched_repos_for_authenticated_user.go b/MCP/tools/activity/activity_list_watched_repos_for_authenticated_user.go new file mode 100644 index 0000000..80a6102 --- /dev/null +++ b/MCP/tools/activity/activity_list_watched_repos_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_watched_repos_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/subscriptions%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_watched_repos_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_subscriptions", + mcp.WithDescription("List repositories watched by the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_watched_repos_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_list_watchers_for_repo.go b/MCP/tools/activity/activity_list_watchers_for_repo.go new file mode 100644 index 0000000..0e8cc33 --- /dev/null +++ b/MCP/tools/activity/activity_list_watchers_for_repo.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_list_watchers_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/subscribers%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_list_watchers_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_subscribers", + mcp.WithDescription("List watchers"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_list_watchers_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_mark_notifications_as_read.go b/MCP/tools/activity/activity_mark_notifications_as_read.go new file mode 100644 index 0000000..8de7118 --- /dev/null +++ b/MCP/tools/activity/activity_mark_notifications_as_read.go @@ -0,0 +1,88 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_mark_notifications_as_readHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/notifications", cfg.BaseURL) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_mark_notifications_as_readTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_notifications", + mcp.WithDescription("Mark notifications as read"), + mcp.WithString("last_read_at", mcp.Description("Input parameter: Describes the last point that notifications were checked. Anything updated since this time will not be marked as read. If you omit this parameter, all notifications are marked as read. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`. Default: The current timestamp.")), + mcp.WithBoolean("read", mcp.Description("Input parameter: Whether the notification has been read.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_mark_notifications_as_readHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_mark_repo_notifications_as_read.go b/MCP/tools/activity/activity_mark_repo_notifications_as_read.go new file mode 100644 index 0000000..741630a --- /dev/null +++ b/MCP/tools/activity/activity_mark_repo_notifications_as_read.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_mark_repo_notifications_as_readHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/notifications", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_mark_repo_notifications_as_readTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_notifications", + mcp.WithDescription("Mark repository notifications as read"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("last_read_at", mcp.Description("Input parameter: Describes the last point that notifications were checked. Anything updated since this time will not be marked as read. If you omit this parameter, all notifications are marked as read. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`. Default: The current timestamp.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_mark_repo_notifications_as_readHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_mark_thread_as_done.go b/MCP/tools/activity/activity_mark_thread_as_done.go new file mode 100644 index 0000000..a6d03cc --- /dev/null +++ b/MCP/tools/activity/activity_mark_thread_as_done.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_mark_thread_as_doneHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + thread_idVal, ok := args["thread_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: thread_id"), nil + } + thread_id, ok := thread_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: thread_id"), nil + } + url := fmt.Sprintf("%s/notifications/threads/%s", cfg.BaseURL, thread_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_mark_thread_as_doneTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_notifications_threads_thread_id", + mcp.WithDescription("Mark a thread as done"), + mcp.WithNumber("thread_id", mcp.Required(), mcp.Description("The unique identifier of the notification thread. This corresponds to the value returned in the `id` field when you retrieve notifications (for example with the [`GET /notifications` operation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_mark_thread_as_doneHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_mark_thread_as_read.go b/MCP/tools/activity/activity_mark_thread_as_read.go new file mode 100644 index 0000000..372a708 --- /dev/null +++ b/MCP/tools/activity/activity_mark_thread_as_read.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_mark_thread_as_readHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + thread_idVal, ok := args["thread_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: thread_id"), nil + } + thread_id, ok := thread_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: thread_id"), nil + } + url := fmt.Sprintf("%s/notifications/threads/%s", cfg.BaseURL, thread_id) + req, err := http.NewRequest("PATCH", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_mark_thread_as_readTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_notifications_threads_thread_id", + mcp.WithDescription("Mark a thread as read"), + mcp.WithNumber("thread_id", mcp.Required(), mcp.Description("The unique identifier of the notification thread. This corresponds to the value returned in the `id` field when you retrieve notifications (for example with the [`GET /notifications` operation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_mark_thread_as_readHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_set_repo_subscription.go b/MCP/tools/activity/activity_set_repo_subscription.go new file mode 100644 index 0000000..d9f5bbf --- /dev/null +++ b/MCP/tools/activity/activity_set_repo_subscription.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_set_repo_subscriptionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/subscription", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_set_repo_subscriptionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_subscription", + mcp.WithDescription("Set a repository subscription"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("ignored", mcp.Description("Input parameter: Determines if all notifications should be blocked from this repository.")), + mcp.WithBoolean("subscribed", mcp.Description("Input parameter: Determines if notifications should be received from this repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_set_repo_subscriptionHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_set_thread_subscription.go b/MCP/tools/activity/activity_set_thread_subscription.go new file mode 100644 index 0000000..52176f1 --- /dev/null +++ b/MCP/tools/activity/activity_set_thread_subscription.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_set_thread_subscriptionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + thread_idVal, ok := args["thread_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: thread_id"), nil + } + thread_id, ok := thread_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: thread_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/notifications/threads/%s/subscription", cfg.BaseURL, thread_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_set_thread_subscriptionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_notifications_threads_thread_id_subscription", + mcp.WithDescription("Set a thread subscription"), + mcp.WithNumber("thread_id", mcp.Required(), mcp.Description("The unique identifier of the notification thread. This corresponds to the value returned in the `id` field when you retrieve notifications (for example with the [`GET /notifications` operation](https://docs.github.com/rest/activity/notifications#list-notifications-for-the-authenticated-user)).")), + mcp.WithBoolean("ignored", mcp.Description("Input parameter: Whether to block all notifications from a thread.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_set_thread_subscriptionHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_star_repo_for_authenticated_user.go b/MCP/tools/activity/activity_star_repo_for_authenticated_user.go new file mode 100644 index 0000000..f214748 --- /dev/null +++ b/MCP/tools/activity/activity_star_repo_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_star_repo_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/user/starred/%s/%s", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_star_repo_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_starred_owner_repo", + mcp.WithDescription("Star a repository for the authenticated user"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_star_repo_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/activity/activity_unstar_repo_for_authenticated_user.go b/MCP/tools/activity/activity_unstar_repo_for_authenticated_user.go new file mode 100644 index 0000000..e46da4a --- /dev/null +++ b/MCP/tools/activity/activity_unstar_repo_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Activity_unstar_repo_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/user/starred/%s/%s", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateActivity_unstar_repo_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_starred_owner_repo", + mcp.WithDescription("Unstar a repository for the authenticated user"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Activity_unstar_repo_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_add_repo_to_installation_for_authenticated_user.go b/MCP/tools/apps/apps_add_repo_to_installation_for_authenticated_user.go new file mode 100644 index 0000000..eb06741 --- /dev/null +++ b/MCP/tools/apps/apps_add_repo_to_installation_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_add_repo_to_installation_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/user/installations/%s/repositories/%s", cfg.BaseURL, installation_id, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_add_repo_to_installation_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_installations_installation_id_repositories_repository_id", + mcp.WithDescription("Add a repository to an app installation"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The unique identifier of the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_add_repo_to_installation_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_check_token.go b/MCP/tools/apps/apps_check_token.go new file mode 100644 index 0000000..e6a5e21 --- /dev/null +++ b/MCP/tools/apps/apps_check_token.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_check_tokenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + client_idVal, ok := args["client_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: client_id"), nil + } + client_id, ok := client_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: client_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/applications/%s/token", cfg.BaseURL, client_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Authorization + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_check_tokenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_applications_client_id_token", + mcp.WithDescription("Check a token"), + mcp.WithString("client_id", mcp.Required(), mcp.Description("The client ID of the GitHub app.")), + mcp.WithString("access_token", mcp.Required(), mcp.Description("Input parameter: The access_token of the OAuth or GitHub application.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_check_tokenHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_create_from_manifest.go b/MCP/tools/apps/apps_create_from_manifest.go new file mode 100644 index 0000000..16fc005 --- /dev/null +++ b/MCP/tools/apps/apps_create_from_manifest.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_create_from_manifestHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codeVal, ok := args["code"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: code"), nil + } + code, ok := codeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: code"), nil + } + url := fmt.Sprintf("%s/app-manifests/%s/conversions", cfg.BaseURL, code) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_create_from_manifestTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_app-manifests_code_conversions", + mcp.WithDescription("Create a GitHub App from a manifest"), + mcp.WithString("code", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_create_from_manifestHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_create_installation_access_token.go b/MCP/tools/apps/apps_create_installation_access_token.go new file mode 100644 index 0000000..d8a4e99 --- /dev/null +++ b/MCP/tools/apps/apps_create_installation_access_token.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_create_installation_access_tokenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/app/installations/%s/access_tokens", cfg.BaseURL, installation_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_create_installation_access_tokenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_app_installations_installation_id_access_tokens", + mcp.WithDescription("Create an installation access token for an app"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + mcp.WithArray("repository_ids", mcp.Description("Input parameter: List of repository IDs that the token should have access to")), + mcp.WithObject("permissions", mcp.Description("Input parameter: The permissions granted to the user access token.")), + mcp.WithArray("repositories", mcp.Description("Input parameter: List of repository names that the token should have access to")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_create_installation_access_tokenHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_delete_authorization.go b/MCP/tools/apps/apps_delete_authorization.go new file mode 100644 index 0000000..602cc4b --- /dev/null +++ b/MCP/tools/apps/apps_delete_authorization.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_delete_authorizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + client_idVal, ok := args["client_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: client_id"), nil + } + client_id, ok := client_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: client_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/applications/%s/grant", cfg.BaseURL, client_id) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_delete_authorizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_applications_client_id_grant", + mcp.WithDescription("Delete an app authorization"), + mcp.WithString("client_id", mcp.Required(), mcp.Description("The client ID of the GitHub app.")), + mcp.WithString("access_token", mcp.Required(), mcp.Description("Input parameter: The OAuth access token used to authenticate to the GitHub API.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_delete_authorizationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_delete_installation.go b/MCP/tools/apps/apps_delete_installation.go new file mode 100644 index 0000000..d54cc2d --- /dev/null +++ b/MCP/tools/apps/apps_delete_installation.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_delete_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + url := fmt.Sprintf("%s/app/installations/%s", cfg.BaseURL, installation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_delete_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_app_installations_installation_id", + mcp.WithDescription("Delete an installation for the authenticated app"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_delete_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_delete_token.go b/MCP/tools/apps/apps_delete_token.go new file mode 100644 index 0000000..5f4b3b4 --- /dev/null +++ b/MCP/tools/apps/apps_delete_token.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_delete_tokenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + client_idVal, ok := args["client_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: client_id"), nil + } + client_id, ok := client_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: client_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/applications/%s/token", cfg.BaseURL, client_id) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_delete_tokenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_applications_client_id_token", + mcp.WithDescription("Delete an app token"), + mcp.WithString("client_id", mcp.Required(), mcp.Description("The client ID of the GitHub app.")), + mcp.WithString("access_token", mcp.Required(), mcp.Description("Input parameter: The OAuth access token used to authenticate to the GitHub API.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_delete_tokenHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_authenticated.go b/MCP/tools/apps/apps_get_authenticated.go new file mode 100644 index 0000000..32c8fb1 --- /dev/null +++ b/MCP/tools/apps/apps_get_authenticated.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_authenticatedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/app", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Integration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_authenticatedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app", + mcp.WithDescription("Get the authenticated app"), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_authenticatedHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_by_slug.go b/MCP/tools/apps/apps_get_by_slug.go new file mode 100644 index 0000000..c19c7ec --- /dev/null +++ b/MCP/tools/apps/apps_get_by_slug.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_by_slugHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + app_slugVal, ok := args["app_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: app_slug"), nil + } + app_slug, ok := app_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: app_slug"), nil + } + url := fmt.Sprintf("%s/apps/%s", cfg.BaseURL, app_slug) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Integration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_by_slugTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_apps_app_slug", + mcp.WithDescription("Get an app"), + mcp.WithString("app_slug", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_by_slugHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_installation.go b/MCP/tools/apps/apps_get_installation.go new file mode 100644 index 0000000..c47251b --- /dev/null +++ b/MCP/tools/apps/apps_get_installation.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + url := fmt.Sprintf("%s/app/installations/%s", cfg.BaseURL, installation_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Installation + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app_installations_installation_id", + mcp.WithDescription("Get an installation for the authenticated app"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_org_installation.go b/MCP/tools/apps/apps_get_org_installation.go new file mode 100644 index 0000000..cf86c63 --- /dev/null +++ b/MCP/tools/apps/apps_get_org_installation.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_org_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/installation", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Installation + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_org_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_installation", + mcp.WithDescription("Get an organization installation for the authenticated app"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_org_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_repo_installation.go b/MCP/tools/apps/apps_get_repo_installation.go new file mode 100644 index 0000000..2dd28fb --- /dev/null +++ b/MCP/tools/apps/apps_get_repo_installation.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_repo_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/installation", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Installation + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_repo_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_installation", + mcp.WithDescription("Get a repository installation for the authenticated app"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_repo_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_subscription_plan_for_account.go b/MCP/tools/apps/apps_get_subscription_plan_for_account.go new file mode 100644 index 0000000..f565172 --- /dev/null +++ b/MCP/tools/apps/apps_get_subscription_plan_for_account.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_subscription_plan_for_accountHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + account_idVal, ok := args["account_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: account_id"), nil + } + account_id, ok := account_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: account_id"), nil + } + url := fmt.Sprintf("%s/marketplace_listing/accounts/%s", cfg.BaseURL, account_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_subscription_plan_for_accountTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_marketplace_listing_accounts_account_id", + mcp.WithDescription("Get a subscription plan for an account"), + mcp.WithNumber("account_id", mcp.Required(), mcp.Description("account_id parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_subscription_plan_for_accountHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_subscription_plan_for_account_stubbed.go b/MCP/tools/apps/apps_get_subscription_plan_for_account_stubbed.go new file mode 100644 index 0000000..c553a83 --- /dev/null +++ b/MCP/tools/apps/apps_get_subscription_plan_for_account_stubbed.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_subscription_plan_for_account_stubbedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + account_idVal, ok := args["account_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: account_id"), nil + } + account_id, ok := account_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: account_id"), nil + } + url := fmt.Sprintf("%s/marketplace_listing/stubbed/accounts/%s", cfg.BaseURL, account_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_subscription_plan_for_account_stubbedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_marketplace_listing_stubbed_accounts_account_id", + mcp.WithDescription("Get a subscription plan for an account (stubbed)"), + mcp.WithNumber("account_id", mcp.Required(), mcp.Description("account_id parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_subscription_plan_for_account_stubbedHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_user_installation.go b/MCP/tools/apps/apps_get_user_installation.go new file mode 100644 index 0000000..b774021 --- /dev/null +++ b/MCP/tools/apps/apps_get_user_installation.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_user_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/installation", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Installation + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_user_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_installation", + mcp.WithDescription("Get a user installation for the authenticated app"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_user_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_webhook_config_for_app.go b/MCP/tools/apps/apps_get_webhook_config_for_app.go new file mode 100644 index 0000000..79a51e3 --- /dev/null +++ b/MCP/tools/apps/apps_get_webhook_config_for_app.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_webhook_config_for_appHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/app/hook/config", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_webhook_config_for_appTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app_hook_config", + mcp.WithDescription("Get a webhook configuration for an app"), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_webhook_config_for_appHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_get_webhook_delivery.go b/MCP/tools/apps/apps_get_webhook_delivery.go new file mode 100644 index 0000000..d9b8039 --- /dev/null +++ b/MCP/tools/apps/apps_get_webhook_delivery.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_get_webhook_deliveryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + delivery_idVal, ok := args["delivery_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: delivery_id"), nil + } + delivery_id, ok := delivery_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: delivery_id"), nil + } + url := fmt.Sprintf("%s/app/hook/deliveries/%s", cfg.BaseURL, delivery_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_get_webhook_deliveryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app_hook_deliveries_delivery_id", + mcp.WithDescription("Get a delivery for an app webhook"), + mcp.WithNumber("delivery_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_get_webhook_deliveryHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_accounts_for_plan.go b/MCP/tools/apps/apps_list_accounts_for_plan.go new file mode 100644 index 0000000..8a5a576 --- /dev/null +++ b/MCP/tools/apps/apps_list_accounts_for_plan.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_accounts_for_planHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + plan_idVal, ok := args["plan_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: plan_id"), nil + } + plan_id, ok := plan_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: plan_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/marketplace_listing/plans/%s/accounts%s", cfg.BaseURL, plan_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_accounts_for_planTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_marketplace_listing_plans_plan_id_accounts", + mcp.WithDescription("List accounts for a plan"), + mcp.WithNumber("plan_id", mcp.Required(), mcp.Description("The unique identifier of the plan.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("To return the oldest accounts first, set to `asc`. Ignored without the `sort` parameter.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_accounts_for_planHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_accounts_for_plan_stubbed.go b/MCP/tools/apps/apps_list_accounts_for_plan_stubbed.go new file mode 100644 index 0000000..4d8b9b4 --- /dev/null +++ b/MCP/tools/apps/apps_list_accounts_for_plan_stubbed.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_accounts_for_plan_stubbedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + plan_idVal, ok := args["plan_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: plan_id"), nil + } + plan_id, ok := plan_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: plan_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/marketplace_listing/stubbed/plans/%s/accounts%s", cfg.BaseURL, plan_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_accounts_for_plan_stubbedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_marketplace_listing_stubbed_plans_plan_id_accounts", + mcp.WithDescription("List accounts for a plan (stubbed)"), + mcp.WithNumber("plan_id", mcp.Required(), mcp.Description("The unique identifier of the plan.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("To return the oldest accounts first, set to `asc`. Ignored without the `sort` parameter.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_accounts_for_plan_stubbedHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_installation_repos_for_authenticated_user.go b/MCP/tools/apps/apps_list_installation_repos_for_authenticated_user.go new file mode 100644 index 0000000..43240bd --- /dev/null +++ b/MCP/tools/apps/apps_list_installation_repos_for_authenticated_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_installation_repos_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/installations/%s/repositories%s", cfg.BaseURL, installation_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_installation_repos_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_installations_installation_id_repositories", + mcp.WithDescription("List repositories accessible to the user access token"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_installation_repos_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_installation_requests_for_authenticated_app.go b/MCP/tools/apps/apps_list_installation_requests_for_authenticated_app.go new file mode 100644 index 0000000..9bcff48 --- /dev/null +++ b/MCP/tools/apps/apps_list_installation_requests_for_authenticated_app.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_installation_requests_for_authenticated_appHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/app/installation-requests%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_installation_requests_for_authenticated_appTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app_installation-requests", + mcp.WithDescription("List installation requests for the authenticated app"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_installation_requests_for_authenticated_appHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_installations.go b/MCP/tools/apps/apps_list_installations.go new file mode 100644 index 0000000..e5b7122 --- /dev/null +++ b/MCP/tools/apps/apps_list_installations.go @@ -0,0 +1,90 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_installationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["outdated"]; ok { + queryParams = append(queryParams, fmt.Sprintf("outdated=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/app/installations%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Installation + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_installationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app_installations", + mcp.WithDescription("List installations for the authenticated app"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("outdated", mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_installationsHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_installations_for_authenticated_user.go b/MCP/tools/apps/apps_list_installations_for_authenticated_user.go new file mode 100644 index 0000000..0aeb4d5 --- /dev/null +++ b/MCP/tools/apps/apps_list_installations_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_installations_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/installations%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_installations_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_installations", + mcp.WithDescription("List app installations accessible to the user access token"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_installations_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_plans.go b/MCP/tools/apps/apps_list_plans.go new file mode 100644 index 0000000..f6ab97e --- /dev/null +++ b/MCP/tools/apps/apps_list_plans.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_plansHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/marketplace_listing/plans%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_plansTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_marketplace_listing_plans", + mcp.WithDescription("List plans"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_plansHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_plans_stubbed.go b/MCP/tools/apps/apps_list_plans_stubbed.go new file mode 100644 index 0000000..e7b8fb0 --- /dev/null +++ b/MCP/tools/apps/apps_list_plans_stubbed.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_plans_stubbedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/marketplace_listing/stubbed/plans%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_plans_stubbedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_marketplace_listing_stubbed_plans", + mcp.WithDescription("List plans (stubbed)"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_plans_stubbedHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_repos_accessible_to_installation.go b/MCP/tools/apps/apps_list_repos_accessible_to_installation.go new file mode 100644 index 0000000..01d77fc --- /dev/null +++ b/MCP/tools/apps/apps_list_repos_accessible_to_installation.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_repos_accessible_to_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/installation/repositories%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_repos_accessible_to_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_installation_repositories", + mcp.WithDescription("List repositories accessible to the app installation"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_repos_accessible_to_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_subscriptions_for_authenticated_user.go b/MCP/tools/apps/apps_list_subscriptions_for_authenticated_user.go new file mode 100644 index 0000000..403aec2 --- /dev/null +++ b/MCP/tools/apps/apps_list_subscriptions_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_subscriptions_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/marketplace_purchases%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_subscriptions_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_marketplace_purchases", + mcp.WithDescription("List subscriptions for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_subscriptions_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_subscriptions_for_authenticated_user_stubbed.go b/MCP/tools/apps/apps_list_subscriptions_for_authenticated_user_stubbed.go new file mode 100644 index 0000000..1f8fb65 --- /dev/null +++ b/MCP/tools/apps/apps_list_subscriptions_for_authenticated_user_stubbed.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_subscriptions_for_authenticated_user_stubbedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/marketplace_purchases/stubbed%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_subscriptions_for_authenticated_user_stubbedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_marketplace_purchases_stubbed", + mcp.WithDescription("List subscriptions for the authenticated user (stubbed)"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_subscriptions_for_authenticated_user_stubbedHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_list_webhook_deliveries.go b/MCP/tools/apps/apps_list_webhook_deliveries.go new file mode 100644 index 0000000..4517998 --- /dev/null +++ b/MCP/tools/apps/apps_list_webhook_deliveries.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_list_webhook_deliveriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["cursor"]; ok { + queryParams = append(queryParams, fmt.Sprintf("cursor=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/app/hook/deliveries%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_list_webhook_deliveriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_app_hook_deliveries", + mcp.WithDescription("List deliveries for an app webhook"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("cursor", mcp.Description("Used for pagination: the starting delivery from which the page of deliveries is fetched. Refer to the `link` header for the next and previous page cursors.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_list_webhook_deliveriesHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_redeliver_webhook_delivery.go b/MCP/tools/apps/apps_redeliver_webhook_delivery.go new file mode 100644 index 0000000..9ef1579 --- /dev/null +++ b/MCP/tools/apps/apps_redeliver_webhook_delivery.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_redeliver_webhook_deliveryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + delivery_idVal, ok := args["delivery_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: delivery_id"), nil + } + delivery_id, ok := delivery_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: delivery_id"), nil + } + url := fmt.Sprintf("%s/app/hook/deliveries/%s/attempts", cfg.BaseURL, delivery_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_redeliver_webhook_deliveryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_app_hook_deliveries_delivery_id_attempts", + mcp.WithDescription("Redeliver a delivery for an app webhook"), + mcp.WithNumber("delivery_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_redeliver_webhook_deliveryHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_remove_repo_from_installation_for_authenticated_user.go b/MCP/tools/apps/apps_remove_repo_from_installation_for_authenticated_user.go new file mode 100644 index 0000000..84bca7f --- /dev/null +++ b/MCP/tools/apps/apps_remove_repo_from_installation_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_remove_repo_from_installation_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/user/installations/%s/repositories/%s", cfg.BaseURL, installation_id, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_remove_repo_from_installation_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_installations_installation_id_repositories_repository_id", + mcp.WithDescription("Remove a repository from an app installation"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The unique identifier of the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_remove_repo_from_installation_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_reset_token.go b/MCP/tools/apps/apps_reset_token.go new file mode 100644 index 0000000..cd542df --- /dev/null +++ b/MCP/tools/apps/apps_reset_token.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_reset_tokenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + client_idVal, ok := args["client_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: client_id"), nil + } + client_id, ok := client_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: client_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/applications/%s/token", cfg.BaseURL, client_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Authorization + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_reset_tokenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_applications_client_id_token", + mcp.WithDescription("Reset a token"), + mcp.WithString("client_id", mcp.Required(), mcp.Description("The client ID of the GitHub app.")), + mcp.WithString("access_token", mcp.Required(), mcp.Description("Input parameter: The access_token of the OAuth or GitHub application.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_reset_tokenHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_revoke_installation_access_token.go b/MCP/tools/apps/apps_revoke_installation_access_token.go new file mode 100644 index 0000000..f15e9d6 --- /dev/null +++ b/MCP/tools/apps/apps_revoke_installation_access_token.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_revoke_installation_access_tokenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/installation/token", cfg.BaseURL) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_revoke_installation_access_tokenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_installation_token", + mcp.WithDescription("Revoke an installation access token"), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_revoke_installation_access_tokenHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_scope_token.go b/MCP/tools/apps/apps_scope_token.go new file mode 100644 index 0000000..f8395fc --- /dev/null +++ b/MCP/tools/apps/apps_scope_token.go @@ -0,0 +1,101 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_scope_tokenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + client_idVal, ok := args["client_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: client_id"), nil + } + client_id, ok := client_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: client_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/applications/%s/token/scoped", cfg.BaseURL, client_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Authorization + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_scope_tokenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_applications_client_id_token_scoped", + mcp.WithDescription("Create a scoped access token"), + mcp.WithString("client_id", mcp.Required(), mcp.Description("The client ID of the GitHub app.")), + mcp.WithString("access_token", mcp.Required(), mcp.Description("Input parameter: The access token used to authenticate to the GitHub API.")), + mcp.WithObject("permissions", mcp.Description("Input parameter: The permissions granted to the user access token.")), + mcp.WithArray("repositories", mcp.Description("Input parameter: The list of repository names to scope the user access token to. `repositories` may not be specified if `repository_ids` is specified.")), + mcp.WithArray("repository_ids", mcp.Description("Input parameter: The list of repository IDs to scope the user access token to. `repository_ids` may not be specified if `repositories` is specified.")), + mcp.WithString("target", mcp.Description("Input parameter: The name of the user or organization to scope the user access token to. **Required** unless `target_id` is specified.")), + mcp.WithNumber("target_id", mcp.Description("Input parameter: The ID of the user or organization to scope the user access token to. **Required** unless `target` is specified.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_scope_tokenHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_suspend_installation.go b/MCP/tools/apps/apps_suspend_installation.go new file mode 100644 index 0000000..a2491fd --- /dev/null +++ b/MCP/tools/apps/apps_suspend_installation.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_suspend_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + url := fmt.Sprintf("%s/app/installations/%s/suspended", cfg.BaseURL, installation_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_suspend_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_app_installations_installation_id_suspended", + mcp.WithDescription("Suspend an app installation"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_suspend_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_unsuspend_installation.go b/MCP/tools/apps/apps_unsuspend_installation.go new file mode 100644 index 0000000..c3d3a06 --- /dev/null +++ b/MCP/tools/apps/apps_unsuspend_installation.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_unsuspend_installationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + installation_idVal, ok := args["installation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: installation_id"), nil + } + installation_id, ok := installation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: installation_id"), nil + } + url := fmt.Sprintf("%s/app/installations/%s/suspended", cfg.BaseURL, installation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_unsuspend_installationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_app_installations_installation_id_suspended", + mcp.WithDescription("Unsuspend an app installation"), + mcp.WithNumber("installation_id", mcp.Required(), mcp.Description("The unique identifier of the installation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_unsuspend_installationHandler(cfg), + } +} diff --git a/MCP/tools/apps/apps_update_webhook_config_for_app.go b/MCP/tools/apps/apps_update_webhook_config_for_app.go new file mode 100644 index 0000000..9c2e119 --- /dev/null +++ b/MCP/tools/apps/apps_update_webhook_config_for_app.go @@ -0,0 +1,90 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Apps_update_webhook_config_for_appHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/app/hook/config", cfg.BaseURL) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApps_update_webhook_config_for_appTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_app_hook_config", + mcp.WithDescription("Update a webhook configuration for an app"), + mcp.WithString("content_type", mcp.Description("Input parameter: The media type used to serialize the payloads. Supported values include `json` and `form`. The default is `form`.")), + mcp.WithString("insecure_ssl", mcp.Description("")), + mcp.WithString("secret", mcp.Description("Input parameter: If provided, the `secret` will be used as the `key` to generate the HMAC hex digest value for [delivery signature headers](https://docs.github.com/webhooks/event-payloads/#delivery-headers).")), + mcp.WithString("url", mcp.Description("Input parameter: The URL to which the payloads will be delivered.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Apps_update_webhook_config_for_appHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_github_actions_billing_org.go b/MCP/tools/billing/billing_get_github_actions_billing_org.go new file mode 100644 index 0000000..42d7810 --- /dev/null +++ b/MCP/tools/billing/billing_get_github_actions_billing_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_github_actions_billing_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/billing/actions", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_github_actions_billing_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_settings_billing_actions", + mcp.WithDescription("Get GitHub Actions billing for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_github_actions_billing_orgHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_github_actions_billing_user.go b/MCP/tools/billing/billing_get_github_actions_billing_user.go new file mode 100644 index 0000000..57f32bb --- /dev/null +++ b/MCP/tools/billing/billing_get_github_actions_billing_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_github_actions_billing_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/settings/billing/actions", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_github_actions_billing_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_settings_billing_actions", + mcp.WithDescription("Get GitHub Actions billing for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_github_actions_billing_userHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_github_billing_usage_report_org.go b/MCP/tools/billing/billing_get_github_billing_usage_report_org.go new file mode 100644 index 0000000..ec432c8 --- /dev/null +++ b/MCP/tools/billing/billing_get_github_billing_usage_report_org.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_github_billing_usage_report_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["year"]; ok { + queryParams = append(queryParams, fmt.Sprintf("year=%v", val)) + } + if val, ok := args["month"]; ok { + queryParams = append(queryParams, fmt.Sprintf("month=%v", val)) + } + if val, ok := args["day"]; ok { + queryParams = append(queryParams, fmt.Sprintf("day=%v", val)) + } + if val, ok := args["hour"]; ok { + queryParams = append(queryParams, fmt.Sprintf("hour=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/organizations/%s/settings/billing/usage%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_github_billing_usage_report_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_organizations_org_settings_billing_usage", + mcp.WithDescription("Get billing usage report for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("year", mcp.Description("If specified, only return results for a single year. The value of `year` is an integer with four digits representing a year. For example, `2025`. Default value is the current year.")), + mcp.WithNumber("month", mcp.Description("If specified, only return results for a single month. The value of `month` is an integer between `1` and `12`. If no year is specified the default `year` is used.")), + mcp.WithNumber("day", mcp.Description("If specified, only return results for a single day. The value of `day` is an integer between `1` and `31`. If no `year` or `month` is specified, the default `year` and `month` are used.")), + mcp.WithNumber("hour", mcp.Description("If specified, only return results for a single hour. The value of `hour` is an integer between `0` and `23`. If no `year`, `month`, or `day` is specified, the default `year`, `month`, and `day` are used.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_github_billing_usage_report_orgHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_github_billing_usage_report_user.go b/MCP/tools/billing/billing_get_github_billing_usage_report_user.go new file mode 100644 index 0000000..14213a2 --- /dev/null +++ b/MCP/tools/billing/billing_get_github_billing_usage_report_user.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_github_billing_usage_report_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["year"]; ok { + queryParams = append(queryParams, fmt.Sprintf("year=%v", val)) + } + if val, ok := args["month"]; ok { + queryParams = append(queryParams, fmt.Sprintf("month=%v", val)) + } + if val, ok := args["day"]; ok { + queryParams = append(queryParams, fmt.Sprintf("day=%v", val)) + } + if val, ok := args["hour"]; ok { + queryParams = append(queryParams, fmt.Sprintf("hour=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/settings/billing/usage%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_github_billing_usage_report_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_settings_billing_usage", + mcp.WithDescription("Get billing usage report for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("year", mcp.Description("If specified, only return results for a single year. The value of `year` is an integer with four digits representing a year. For example, `2025`. Default value is the current year.")), + mcp.WithNumber("month", mcp.Description("If specified, only return results for a single month. The value of `month` is an integer between `1` and `12`. If no year is specified the default `year` is used.")), + mcp.WithNumber("day", mcp.Description("If specified, only return results for a single day. The value of `day` is an integer between `1` and `31`. If no `year` or `month` is specified, the default `year` and `month` are used.")), + mcp.WithNumber("hour", mcp.Description("If specified, only return results for a single hour. The value of `hour` is an integer between `0` and `23`. If no `year`, `month`, or `day` is specified, the default `year`, `month`, and `day` are used.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_github_billing_usage_report_userHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_github_packages_billing_org.go b/MCP/tools/billing/billing_get_github_packages_billing_org.go new file mode 100644 index 0000000..9661790 --- /dev/null +++ b/MCP/tools/billing/billing_get_github_packages_billing_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_github_packages_billing_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/billing/packages", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_github_packages_billing_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_settings_billing_packages", + mcp.WithDescription("Get GitHub Packages billing for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_github_packages_billing_orgHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_github_packages_billing_user.go b/MCP/tools/billing/billing_get_github_packages_billing_user.go new file mode 100644 index 0000000..8892ae3 --- /dev/null +++ b/MCP/tools/billing/billing_get_github_packages_billing_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_github_packages_billing_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/settings/billing/packages", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_github_packages_billing_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_settings_billing_packages", + mcp.WithDescription("Get GitHub Packages billing for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_github_packages_billing_userHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_shared_storage_billing_org.go b/MCP/tools/billing/billing_get_shared_storage_billing_org.go new file mode 100644 index 0000000..640b9b1 --- /dev/null +++ b/MCP/tools/billing/billing_get_shared_storage_billing_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_shared_storage_billing_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/billing/shared-storage", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_shared_storage_billing_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_settings_billing_shared-storage", + mcp.WithDescription("Get shared storage billing for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_shared_storage_billing_orgHandler(cfg), + } +} diff --git a/MCP/tools/billing/billing_get_shared_storage_billing_user.go b/MCP/tools/billing/billing_get_shared_storage_billing_user.go new file mode 100644 index 0000000..be15058 --- /dev/null +++ b/MCP/tools/billing/billing_get_shared_storage_billing_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Billing_get_shared_storage_billing_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/settings/billing/shared-storage", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateBilling_get_shared_storage_billing_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_settings_billing_shared-storage", + mcp.WithDescription("Get shared storage billing for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Billing_get_shared_storage_billing_userHandler(cfg), + } +} diff --git a/MCP/tools/campaigns/campaigns_create_campaign.go b/MCP/tools/campaigns/campaigns_create_campaign.go new file mode 100644 index 0000000..8ed12b2 --- /dev/null +++ b/MCP/tools/campaigns/campaigns_create_campaign.go @@ -0,0 +1,103 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Campaigns_create_campaignHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/campaigns", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCampaigns_create_campaignTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_campaigns", + mcp.WithDescription("Create a campaign for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithBoolean("generate_issues", mcp.Description("Input parameter: If true, will automatically generate issues for the campaign. The default is false.")), + mcp.WithArray("managers", mcp.Description("Input parameter: The logins of the users to set as the campaign managers. At this time, only a single manager can be supplied.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the campaign")), + mcp.WithArray("team_managers", mcp.Description("Input parameter: The slugs of the teams to set as the campaign managers.")), + mcp.WithArray("code_scanning_alerts", mcp.Required(), mcp.Description("Input parameter: The code scanning alerts to include in this campaign")), + mcp.WithString("contact_link", mcp.Description("Input parameter: The contact link of the campaign. Must be a URI.")), + mcp.WithString("description", mcp.Required(), mcp.Description("Input parameter: A description for the campaign")), + mcp.WithString("ends_at", mcp.Required(), mcp.Description("Input parameter: The end date and time of the campaign. The date must be in the future.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Campaigns_create_campaignHandler(cfg), + } +} diff --git a/MCP/tools/campaigns/campaigns_delete_campaign.go b/MCP/tools/campaigns/campaigns_delete_campaign.go new file mode 100644 index 0000000..38f04f1 --- /dev/null +++ b/MCP/tools/campaigns/campaigns_delete_campaign.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Campaigns_delete_campaignHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + campaign_numberVal, ok := args["campaign_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: campaign_number"), nil + } + campaign_number, ok := campaign_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: campaign_number"), nil + } + url := fmt.Sprintf("%s/orgs/%s/campaigns/%s", cfg.BaseURL, org, campaign_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCampaigns_delete_campaignTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_campaigns_campaign_number", + mcp.WithDescription("Delete a campaign for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("campaign_number", mcp.Required(), mcp.Description("The campaign number.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Campaigns_delete_campaignHandler(cfg), + } +} diff --git a/MCP/tools/campaigns/campaigns_get_campaign_summary.go b/MCP/tools/campaigns/campaigns_get_campaign_summary.go new file mode 100644 index 0000000..6848a3b --- /dev/null +++ b/MCP/tools/campaigns/campaigns_get_campaign_summary.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Campaigns_get_campaign_summaryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + campaign_numberVal, ok := args["campaign_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: campaign_number"), nil + } + campaign_number, ok := campaign_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: campaign_number"), nil + } + url := fmt.Sprintf("%s/orgs/%s/campaigns/%s", cfg.BaseURL, org, campaign_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCampaigns_get_campaign_summaryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_campaigns_campaign_number", + mcp.WithDescription("Get a campaign for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("campaign_number", mcp.Required(), mcp.Description("The campaign number.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Campaigns_get_campaign_summaryHandler(cfg), + } +} diff --git a/MCP/tools/campaigns/campaigns_list_org_campaigns.go b/MCP/tools/campaigns/campaigns_list_org_campaigns.go new file mode 100644 index 0000000..870189a --- /dev/null +++ b/MCP/tools/campaigns/campaigns_list_org_campaigns.go @@ -0,0 +1,103 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Campaigns_list_org_campaignsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/campaigns%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCampaigns_list_org_campaignsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_campaigns", + mcp.WithDescription("List campaigns for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("state", mcp.Description("If specified, only campaigns with this state will be returned.")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Campaigns_list_org_campaignsHandler(cfg), + } +} diff --git a/MCP/tools/campaigns/campaigns_update_campaign.go b/MCP/tools/campaigns/campaigns_update_campaign.go new file mode 100644 index 0000000..b2518c5 --- /dev/null +++ b/MCP/tools/campaigns/campaigns_update_campaign.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Campaigns_update_campaignHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + campaign_numberVal, ok := args["campaign_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: campaign_number"), nil + } + campaign_number, ok := campaign_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: campaign_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/campaigns/%s", cfg.BaseURL, org, campaign_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCampaigns_update_campaignTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_campaigns_campaign_number", + mcp.WithDescription("Update a campaign"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("campaign_number", mcp.Required(), mcp.Description("The campaign number.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the campaign")), + mcp.WithString("state", mcp.Description("Input parameter: Indicates whether a campaign is open or closed")), + mcp.WithArray("team_managers", mcp.Description("Input parameter: The slugs of the teams to set as the campaign managers.")), + mcp.WithString("contact_link", mcp.Description("Input parameter: The contact link of the campaign. Must be a URI.")), + mcp.WithString("description", mcp.Description("Input parameter: A description for the campaign")), + mcp.WithString("ends_at", mcp.Description("Input parameter: The end date and time of the campaign, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ.")), + mcp.WithArray("managers", mcp.Description("Input parameter: The logins of the users to set as the campaign managers. At this time, only a single manager can be supplied.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Campaigns_update_campaignHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_create.go b/MCP/tools/checks/checks_create.go new file mode 100644 index 0000000..23445a7 --- /dev/null +++ b/MCP/tools/checks/checks_create.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_createHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-runs", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_createTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_check-runs", + mcp.WithDescription("Create a check run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("conclusion", mcp.Description("Input parameter: **Required if you provide `completed_at` or a `status` of `completed`**. The final conclusion of the check. \n**Note:** Providing `conclusion` will automatically set the `status` parameter to `completed`. You cannot change a check run conclusion to `stale`, only GitHub can set this.")), + mcp.WithString("details_url", mcp.Description("Input parameter: The URL of the integrator's site that has the full details of the check. If the integrator does not provide this, then the homepage of the GitHub app is used.")), + mcp.WithString("external_id", mcp.Description("Input parameter: A reference for the run on the integrator's system.")), + mcp.WithArray("actions", mcp.Description("Input parameter: Displays a button on GitHub that can be clicked to alert your app to do additional tasks. For example, a code linting app can display a button that automatically fixes detected errors. The button created in this object is displayed after the check run completes. When a user clicks the button, GitHub sends the [`check_run.requested_action` webhook](https://docs.github.com/webhooks/event-payloads/#check_run) to your app. Each action includes a `label`, `identifier` and `description`. A maximum of three actions are accepted. To learn more about check runs and requested actions, see \"[Check runs and requested actions](https://docs.github.com/rest/guides/using-the-rest-api-to-interact-with-checks#check-runs-and-requested-actions).\"")), + mcp.WithObject("output", mcp.Description("Input parameter: Check runs can accept a variety of data in the `output` object, including a `title` and `summary` and can optionally provide descriptive details about the run.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the check. For example, \"code-coverage\".")), + mcp.WithString("status", mcp.Description("Input parameter: The current status of the check run. Only GitHub Actions can set a status of `waiting`, `pending`, or `requested`.")), + mcp.WithString("completed_at", mcp.Description("Input parameter: The time the check completed. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("head_sha", mcp.Required(), mcp.Description("Input parameter: The SHA of the commit.")), + mcp.WithString("started_at", mcp.Description("Input parameter: The time that the check run began. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_createHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_create_suite.go b/MCP/tools/checks/checks_create_suite.go new file mode 100644 index 0000000..1bd303d --- /dev/null +++ b/MCP/tools/checks/checks_create_suite.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_create_suiteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-suites", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_create_suiteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_check-suites", + mcp.WithDescription("Create a check suite"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("head_sha", mcp.Required(), mcp.Description("Input parameter: The sha of the head commit.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_create_suiteHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_get.go b/MCP/tools/checks/checks_get.go new file mode 100644 index 0000000..fea3215 --- /dev/null +++ b/MCP/tools/checks/checks_get.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_run_idVal, ok := args["check_run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_run_id"), nil + } + check_run_id, ok := check_run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-runs/%s", cfg.BaseURL, owner, repo, check_run_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_check-runs_check_run_id", + mcp.WithDescription("Get a check run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_run_id", mcp.Required(), mcp.Description("The unique identifier of the check run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_getHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_get_suite.go b/MCP/tools/checks/checks_get_suite.go new file mode 100644 index 0000000..5387605 --- /dev/null +++ b/MCP/tools/checks/checks_get_suite.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_get_suiteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_suite_idVal, ok := args["check_suite_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_suite_id"), nil + } + check_suite_id, ok := check_suite_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_suite_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-suites/%s", cfg.BaseURL, owner, repo, check_suite_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_get_suiteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_check-suites_check_suite_id", + mcp.WithDescription("Get a check suite"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_suite_id", mcp.Required(), mcp.Description("The unique identifier of the check suite.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_get_suiteHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_list_annotations.go b/MCP/tools/checks/checks_list_annotations.go new file mode 100644 index 0000000..bc6ac2f --- /dev/null +++ b/MCP/tools/checks/checks_list_annotations.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_list_annotationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_run_idVal, ok := args["check_run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_run_id"), nil + } + check_run_id, ok := check_run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_run_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/check-runs/%s/annotations%s", cfg.BaseURL, owner, repo, check_run_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_list_annotationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_check-runs_check_run_id_annotations", + mcp.WithDescription("List check run annotations"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_run_id", mcp.Required(), mcp.Description("The unique identifier of the check run.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_list_annotationsHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_list_for_ref.go b/MCP/tools/checks/checks_list_for_ref.go new file mode 100644 index 0000000..f2cdfb8 --- /dev/null +++ b/MCP/tools/checks/checks_list_for_ref.go @@ -0,0 +1,125 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_list_for_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + queryParams := make([]string, 0) + if val, ok := args["check_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("check_name=%v", val)) + } + if val, ok := args["status"]; ok { + queryParams = append(queryParams, fmt.Sprintf("status=%v", val)) + } + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["app_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("app_id=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/check-runs%s", cfg.BaseURL, owner, repo, ref, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_list_for_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_ref_check-runs", + mcp.WithDescription("List check runs for a Git reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The commit reference. Can be a commit SHA, branch name (`heads/BRANCH_NAME`), or tag name (`tags/TAG_NAME`). For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + mcp.WithString("check_name", mcp.Description("Returns check runs with the specified `name`.")), + mcp.WithString("status", mcp.Description("Returns check runs with the specified `status`.")), + mcp.WithString("filter", mcp.Description("Filters check runs by their `completed_at` timestamp. `latest` returns the most recent check runs.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("app_id", mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_list_for_refHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_list_for_suite.go b/MCP/tools/checks/checks_list_for_suite.go new file mode 100644 index 0000000..79a6fe8 --- /dev/null +++ b/MCP/tools/checks/checks_list_for_suite.go @@ -0,0 +1,121 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_list_for_suiteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_suite_idVal, ok := args["check_suite_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_suite_id"), nil + } + check_suite_id, ok := check_suite_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_suite_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["check_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("check_name=%v", val)) + } + if val, ok := args["status"]; ok { + queryParams = append(queryParams, fmt.Sprintf("status=%v", val)) + } + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/check-suites/%s/check-runs%s", cfg.BaseURL, owner, repo, check_suite_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_list_for_suiteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_check-suites_check_suite_id_check-runs", + mcp.WithDescription("List check runs in a check suite"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_suite_id", mcp.Required(), mcp.Description("The unique identifier of the check suite.")), + mcp.WithString("check_name", mcp.Description("Returns check runs with the specified `name`.")), + mcp.WithString("status", mcp.Description("Returns check runs with the specified `status`.")), + mcp.WithString("filter", mcp.Description("Filters check runs by their `completed_at` timestamp. `latest` returns the most recent check runs.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_list_for_suiteHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_list_suites_for_ref.go b/MCP/tools/checks/checks_list_suites_for_ref.go new file mode 100644 index 0000000..032ad63 --- /dev/null +++ b/MCP/tools/checks/checks_list_suites_for_ref.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_list_suites_for_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + queryParams := make([]string, 0) + if val, ok := args["app_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("app_id=%v", val)) + } + if val, ok := args["check_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("check_name=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/check-suites%s", cfg.BaseURL, owner, repo, ref, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_list_suites_for_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_ref_check-suites", + mcp.WithDescription("List check suites for a Git reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The commit reference. Can be a commit SHA, branch name (`heads/BRANCH_NAME`), or tag name (`tags/TAG_NAME`). For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + mcp.WithNumber("app_id", mcp.Description("Filters check suites by GitHub App `id`.")), + mcp.WithString("check_name", mcp.Description("Returns check runs with the specified `name`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_list_suites_for_refHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_rerequest_run.go b/MCP/tools/checks/checks_rerequest_run.go new file mode 100644 index 0000000..2bedc14 --- /dev/null +++ b/MCP/tools/checks/checks_rerequest_run.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_rerequest_runHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_run_idVal, ok := args["check_run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_run_id"), nil + } + check_run_id, ok := check_run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_run_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-runs/%s/rerequest", cfg.BaseURL, owner, repo, check_run_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_rerequest_runTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_check-runs_check_run_id_rerequest", + mcp.WithDescription("Rerequest a check run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_run_id", mcp.Required(), mcp.Description("The unique identifier of the check run.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_rerequest_runHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_rerequest_suite.go b/MCP/tools/checks/checks_rerequest_suite.go new file mode 100644 index 0000000..f987b68 --- /dev/null +++ b/MCP/tools/checks/checks_rerequest_suite.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_rerequest_suiteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_suite_idVal, ok := args["check_suite_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_suite_id"), nil + } + check_suite_id, ok := check_suite_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_suite_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-suites/%s/rerequest", cfg.BaseURL, owner, repo, check_suite_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_rerequest_suiteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_check-suites_check_suite_id_rerequest", + mcp.WithDescription("Rerequest a check suite"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_suite_id", mcp.Required(), mcp.Description("The unique identifier of the check suite.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_rerequest_suiteHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_set_suites_preferences.go b/MCP/tools/checks/checks_set_suites_preferences.go new file mode 100644 index 0000000..312fce3 --- /dev/null +++ b/MCP/tools/checks/checks_set_suites_preferences.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_set_suites_preferencesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-suites/preferences", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_set_suites_preferencesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_check-suites_preferences", + mcp.WithDescription("Update repository preferences for check suites"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("auto_trigger_checks", mcp.Description("Input parameter: Enables or disables automatic creation of CheckSuite events upon pushes to the repository. Enabled by default.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_set_suites_preferencesHandler(cfg), + } +} diff --git a/MCP/tools/checks/checks_update.go b/MCP/tools/checks/checks_update.go new file mode 100644 index 0000000..0922b6c --- /dev/null +++ b/MCP/tools/checks/checks_update.go @@ -0,0 +1,122 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Checks_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + check_run_idVal, ok := args["check_run_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: check_run_id"), nil + } + check_run_id, ok := check_run_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: check_run_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/check-runs/%s", cfg.BaseURL, owner, repo, check_run_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateChecks_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_check-runs_check_run_id", + mcp.WithDescription("Update a check run"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("check_run_id", mcp.Required(), mcp.Description("The unique identifier of the check run.")), + mcp.WithObject("output", mcp.Description("Input parameter: Check runs can accept a variety of data in the `output` object, including a `title` and `summary` and can optionally provide descriptive details about the run.")), + mcp.WithString("started_at", mcp.Description("Input parameter: This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("status", mcp.Description("Input parameter: The current status of the check run. Only GitHub Actions can set a status of `waiting`, `pending`, or `requested`.")), + mcp.WithArray("actions", mcp.Description("Input parameter: Possible further actions the integrator can perform, which a user may trigger. Each action includes a `label`, `identifier` and `description`. A maximum of three actions are accepted. To learn more about check runs and requested actions, see \"[Check runs and requested actions](https://docs.github.com/rest/guides/using-the-rest-api-to-interact-with-checks#check-runs-and-requested-actions).\"")), + mcp.WithString("details_url", mcp.Description("Input parameter: The URL of the integrator's site that has the full details of the check.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the check. For example, \"code-coverage\".")), + mcp.WithString("completed_at", mcp.Description("Input parameter: The time the check completed. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("conclusion", mcp.Description("Input parameter: **Required if you provide `completed_at` or a `status` of `completed`**. The final conclusion of the check. \n**Note:** Providing `conclusion` will automatically set the `status` parameter to `completed`. You cannot change a check run conclusion to `stale`, only GitHub can set this.")), + mcp.WithString("external_id", mcp.Description("Input parameter: A reference for the run on the integrator's system.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Checks_updateHandler(cfg), + } +} diff --git a/MCP/tools/classroom/classroom_get_a_classroom.go b/MCP/tools/classroom/classroom_get_a_classroom.go new file mode 100644 index 0000000..2d463f9 --- /dev/null +++ b/MCP/tools/classroom/classroom_get_a_classroom.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Classroom_get_a_classroomHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + classroom_idVal, ok := args["classroom_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: classroom_id"), nil + } + classroom_id, ok := classroom_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: classroom_id"), nil + } + url := fmt.Sprintf("%s/classrooms/%s", cfg.BaseURL, classroom_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Classroom + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateClassroom_get_a_classroomTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_classrooms_classroom_id", + mcp.WithDescription("Get a classroom"), + mcp.WithNumber("classroom_id", mcp.Required(), mcp.Description("The unique identifier of the classroom.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Classroom_get_a_classroomHandler(cfg), + } +} diff --git a/MCP/tools/classroom/classroom_get_an_assignment.go b/MCP/tools/classroom/classroom_get_an_assignment.go new file mode 100644 index 0000000..1db5609 --- /dev/null +++ b/MCP/tools/classroom/classroom_get_an_assignment.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Classroom_get_an_assignmentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + assignment_idVal, ok := args["assignment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: assignment_id"), nil + } + assignment_id, ok := assignment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: assignment_id"), nil + } + url := fmt.Sprintf("%s/assignments/%s", cfg.BaseURL, assignment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateClassroom_get_an_assignmentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_assignments_assignment_id", + mcp.WithDescription("Get an assignment"), + mcp.WithNumber("assignment_id", mcp.Required(), mcp.Description("The unique identifier of the classroom assignment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Classroom_get_an_assignmentHandler(cfg), + } +} diff --git a/MCP/tools/classroom/classroom_get_assignment_grades.go b/MCP/tools/classroom/classroom_get_assignment_grades.go new file mode 100644 index 0000000..0228e16 --- /dev/null +++ b/MCP/tools/classroom/classroom_get_assignment_grades.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Classroom_get_assignment_gradesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + assignment_idVal, ok := args["assignment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: assignment_id"), nil + } + assignment_id, ok := assignment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: assignment_id"), nil + } + url := fmt.Sprintf("%s/assignments/%s/grades", cfg.BaseURL, assignment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateClassroom_get_assignment_gradesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_assignments_assignment_id_grades", + mcp.WithDescription("Get assignment grades"), + mcp.WithNumber("assignment_id", mcp.Required(), mcp.Description("The unique identifier of the classroom assignment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Classroom_get_assignment_gradesHandler(cfg), + } +} diff --git a/MCP/tools/classroom/classroom_list_accepted_assignments_for_an_assignment.go b/MCP/tools/classroom/classroom_list_accepted_assignments_for_an_assignment.go new file mode 100644 index 0000000..ab2584e --- /dev/null +++ b/MCP/tools/classroom/classroom_list_accepted_assignments_for_an_assignment.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Classroom_list_accepted_assignments_for_an_assignmentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + assignment_idVal, ok := args["assignment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: assignment_id"), nil + } + assignment_id, ok := assignment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: assignment_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/assignments/%s/accepted_assignments%s", cfg.BaseURL, assignment_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateClassroom_list_accepted_assignments_for_an_assignmentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_assignments_assignment_id_accepted_assignments", + mcp.WithDescription("List accepted assignments for an assignment"), + mcp.WithNumber("assignment_id", mcp.Required(), mcp.Description("The unique identifier of the classroom assignment.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Classroom_list_accepted_assignments_for_an_assignmentHandler(cfg), + } +} diff --git a/MCP/tools/classroom/classroom_list_assignments_for_a_classroom.go b/MCP/tools/classroom/classroom_list_assignments_for_a_classroom.go new file mode 100644 index 0000000..60081ad --- /dev/null +++ b/MCP/tools/classroom/classroom_list_assignments_for_a_classroom.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Classroom_list_assignments_for_a_classroomHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + classroom_idVal, ok := args["classroom_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: classroom_id"), nil + } + classroom_id, ok := classroom_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: classroom_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/classrooms/%s/assignments%s", cfg.BaseURL, classroom_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateClassroom_list_assignments_for_a_classroomTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_classrooms_classroom_id_assignments", + mcp.WithDescription("List assignments for a classroom"), + mcp.WithNumber("classroom_id", mcp.Required(), mcp.Description("The unique identifier of the classroom.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Classroom_list_assignments_for_a_classroomHandler(cfg), + } +} diff --git a/MCP/tools/classroom/classroom_list_classrooms.go b/MCP/tools/classroom/classroom_list_classrooms.go new file mode 100644 index 0000000..f66cb78 --- /dev/null +++ b/MCP/tools/classroom/classroom_list_classrooms.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Classroom_list_classroomsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/classrooms%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateClassroom_list_classroomsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_classrooms", + mcp.WithDescription("List classrooms"), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Classroom_list_classroomsHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_commit_autofix.go b/MCP/tools/code_scanning/code_scanning_commit_autofix.go new file mode 100644 index 0000000..171b20d --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_commit_autofix.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_commit_autofixHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts/%s/autofix/commits", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_commit_autofixTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_code-scanning_alerts_alert_number_autofix_commits", + mcp.WithDescription("Commit an autofix for a code scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + mcp.WithString("message", mcp.Description("Input parameter: Commit message to be used.")), + mcp.WithString("target_ref", mcp.Description("Input parameter: The Git reference of target branch for the commit. Branch needs to already exist. For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_commit_autofixHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_create_autofix.go b/MCP/tools/code_scanning/code_scanning_create_autofix.go new file mode 100644 index 0000000..f65c036 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_create_autofix.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_create_autofixHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts/%s/autofix", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_create_autofixTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_code-scanning_alerts_alert_number_autofix", + mcp.WithDescription("Create an autofix for a code scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_create_autofixHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_create_variant_analysis.go b/MCP/tools/code_scanning/code_scanning_create_variant_analysis.go new file mode 100644 index 0000000..4134b1d --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_create_variant_analysis.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_create_variant_analysisHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/codeql/variant-analyses", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_create_variant_analysisTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_code-scanning_codeql_variant-analyses", + mcp.WithDescription("Create a CodeQL variant analysis"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("repository_owners", mcp.Description("Input parameter: List of organization or user names whose repositories the query should be run against. Precisely one property from `repositories`, `repository_lists` and `repository_owners` is required.")), + mcp.WithString("language", mcp.Required(), mcp.Description("Input parameter: The language targeted by the CodeQL query")), + mcp.WithString("query_pack", mcp.Required(), mcp.Description("Input parameter: A Base64-encoded tarball containing a CodeQL query and all its dependencies")), + mcp.WithArray("repositories", mcp.Description("Input parameter: List of repository names (in the form `owner/repo-name`) to run the query against. Precisely one property from `repositories`, `repository_lists` and `repository_owners` is required.")), + mcp.WithArray("repository_lists", mcp.Description("Input parameter: List of repository lists to run the query against. Precisely one property from `repositories`, `repository_lists` and `repository_owners` is required.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_create_variant_analysisHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_delete_analysis.go b/MCP/tools/code_scanning/code_scanning_delete_analysis.go new file mode 100644 index 0000000..aacf682 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_delete_analysis.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_delete_analysisHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + analysis_idVal, ok := args["analysis_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: analysis_id"), nil + } + analysis_id, ok := analysis_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: analysis_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["confirm_delete"]; ok { + queryParams = append(queryParams, fmt.Sprintf("confirm_delete=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/analyses/%s%s", cfg.BaseURL, owner, repo, analysis_id, queryString) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_delete_analysisTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_code-scanning_analyses_analysis_id", + mcp.WithDescription("Delete a code scanning analysis from a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("analysis_id", mcp.Required(), mcp.Description("The ID of the analysis, as returned from the `GET /repos/{owner}/{repo}/code-scanning/analyses` operation.")), + mcp.WithString("confirm_delete", mcp.Description("Allow deletion if the specified analysis is the last in a set. If you attempt to delete the final analysis in a set without setting this parameter to `true`, you'll get a 400 response with the message: `Analysis is last of its type and deletion may result in the loss of historical alert data. Please specify confirm_delete.`")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_delete_analysisHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_delete_codeql_database.go b/MCP/tools/code_scanning/code_scanning_delete_codeql_database.go new file mode 100644 index 0000000..12940eb --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_delete_codeql_database.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_delete_codeql_databaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + languageVal, ok := args["language"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: language"), nil + } + language, ok := languageVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: language"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/codeql/databases/%s", cfg.BaseURL, owner, repo, language) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_delete_codeql_databaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_code-scanning_codeql_databases_language", + mcp.WithDescription("Delete a CodeQL database"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("language", mcp.Required(), mcp.Description("The language of the CodeQL database.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_delete_codeql_databaseHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_alert.go b/MCP/tools/code_scanning/code_scanning_get_alert.go new file mode 100644 index 0000000..c221fe6 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_alert.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts/%s", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_alerts_alert_number", + mcp.WithDescription("Get a code scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_alertHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_analysis.go b/MCP/tools/code_scanning/code_scanning_get_analysis.go new file mode 100644 index 0000000..3c9163e --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_analysis.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_analysisHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + analysis_idVal, ok := args["analysis_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: analysis_id"), nil + } + analysis_id, ok := analysis_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: analysis_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/analyses/%s", cfg.BaseURL, owner, repo, analysis_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_analysisTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_analyses_analysis_id", + mcp.WithDescription("Get a code scanning analysis for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("analysis_id", mcp.Required(), mcp.Description("The ID of the analysis, as returned from the `GET /repos/{owner}/{repo}/code-scanning/analyses` operation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_analysisHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_autofix.go b/MCP/tools/code_scanning/code_scanning_get_autofix.go new file mode 100644 index 0000000..f25ef0e --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_autofix.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_autofixHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts/%s/autofix", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_autofixTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_alerts_alert_number_autofix", + mcp.WithDescription("Get the status of an autofix for a code scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_autofixHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_codeql_database.go b/MCP/tools/code_scanning/code_scanning_get_codeql_database.go new file mode 100644 index 0000000..bf13634 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_codeql_database.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_codeql_databaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + languageVal, ok := args["language"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: language"), nil + } + language, ok := languageVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: language"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/codeql/databases/%s", cfg.BaseURL, owner, repo, language) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_codeql_databaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_codeql_databases_language", + mcp.WithDescription("Get a CodeQL database for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("language", mcp.Required(), mcp.Description("The language of the CodeQL database.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_codeql_databaseHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_default_setup.go b/MCP/tools/code_scanning/code_scanning_get_default_setup.go new file mode 100644 index 0000000..a7ff248 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_default_setup.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_default_setupHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/default-setup", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_default_setupTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_default-setup", + mcp.WithDescription("Get a code scanning default setup configuration"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_default_setupHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_sarif.go b/MCP/tools/code_scanning/code_scanning_get_sarif.go new file mode 100644 index 0000000..b6a50bb --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_sarif.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_sarifHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + sarif_idVal, ok := args["sarif_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: sarif_id"), nil + } + sarif_id, ok := sarif_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: sarif_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/sarifs/%s", cfg.BaseURL, owner, repo, sarif_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_sarifTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_sarifs_sarif_id", + mcp.WithDescription("Get information about a SARIF upload"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sarif_id", mcp.Required(), mcp.Description("The SARIF ID obtained after uploading.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_sarifHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_variant_analysis.go b/MCP/tools/code_scanning/code_scanning_get_variant_analysis.go new file mode 100644 index 0000000..1c201c5 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_variant_analysis.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_variant_analysisHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + codeql_variant_analysis_idVal, ok := args["codeql_variant_analysis_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codeql_variant_analysis_id"), nil + } + codeql_variant_analysis_id, ok := codeql_variant_analysis_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codeql_variant_analysis_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/codeql/variant-analyses/%s", cfg.BaseURL, owner, repo, codeql_variant_analysis_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_variant_analysisTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_codeql_variant-analyses_codeql_variant_analysis_id", + mcp.WithDescription("Get the summary of a CodeQL variant analysis"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("codeql_variant_analysis_id", mcp.Required(), mcp.Description("The unique identifier of the variant analysis.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_variant_analysisHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_get_variant_analysis_repo_task.go b/MCP/tools/code_scanning/code_scanning_get_variant_analysis_repo_task.go new file mode 100644 index 0000000..db4b081 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_get_variant_analysis_repo_task.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_get_variant_analysis_repo_taskHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + codeql_variant_analysis_idVal, ok := args["codeql_variant_analysis_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codeql_variant_analysis_id"), nil + } + codeql_variant_analysis_id, ok := codeql_variant_analysis_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codeql_variant_analysis_id"), nil + } + repo_ownerVal, ok := args["repo_owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo_owner"), nil + } + repo_owner, ok := repo_ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo_owner"), nil + } + repo_nameVal, ok := args["repo_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo_name"), nil + } + repo_name, ok := repo_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/codeql/variant-analyses/%s/repos/%s/%s", cfg.BaseURL, owner, repo, codeql_variant_analysis_id, repo_owner, repo_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_get_variant_analysis_repo_taskTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_codeql_variant-analyses_codeql_variant_analysis_id_repos_repo_owner_repo_name", + mcp.WithDescription("Get the analysis status of a repository in a CodeQL variant analysis"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the controller repository.")), + mcp.WithNumber("codeql_variant_analysis_id", mcp.Required(), mcp.Description("The ID of the variant analysis.")), + mcp.WithString("repo_owner", mcp.Required(), mcp.Description("The account owner of the variant analysis repository. The name is not case sensitive.")), + mcp.WithString("repo_name", mcp.Required(), mcp.Description("The name of the variant analysis repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_get_variant_analysis_repo_taskHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_list_alert_instances.go b/MCP/tools/code_scanning/code_scanning_list_alert_instances.go new file mode 100644 index 0000000..0df4b2b --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_list_alert_instances.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_list_alert_instancesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["pr"]; ok { + queryParams = append(queryParams, fmt.Sprintf("pr=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts/%s/instances%s", cfg.BaseURL, owner, repo, alert_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_list_alert_instancesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_alerts_alert_number_instances", + mcp.WithDescription("List instances of a code scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("ref", mcp.Description("The Git reference for the results you want to list. The `ref` for a branch can be formatted either as `refs/heads/` or simply ``. To reference a pull request use `refs/pull//merge`.")), + mcp.WithNumber("pr", mcp.Description("The number of the pull request for the results you want to list.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_list_alert_instancesHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_list_alerts_for_org.go b/MCP/tools/code_scanning/code_scanning_list_alerts_for_org.go new file mode 100644 index 0000000..9699c71 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_list_alerts_for_org.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_list_alerts_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["tool_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("tool_name=%v", val)) + } + if val, ok := args["tool_guid"]; ok { + queryParams = append(queryParams, fmt.Sprintf("tool_guid=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["severity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("severity=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/code-scanning/alerts%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_list_alerts_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_code-scanning_alerts", + mcp.WithDescription("List code scanning alerts for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("tool_name", mcp.Description("The name of a code scanning tool. Only results by this tool will be listed. You can specify the tool by using either `tool_name` or `tool_guid`, but not both.")), + mcp.WithString("tool_guid", mcp.Description("The GUID of a code scanning tool. Only results by this tool will be listed. Note that some code scanning tools may not include a GUID in their analysis data. You can specify the tool by using either `tool_guid` or `tool_name`, but not both.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("state", mcp.Description("If specified, only code scanning alerts with this state will be returned.")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.")), + mcp.WithString("severity", mcp.Description("If specified, only code scanning alerts with this severity will be returned.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_list_alerts_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_list_alerts_for_repo.go b/MCP/tools/code_scanning/code_scanning_list_alerts_for_repo.go new file mode 100644 index 0000000..68c662a --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_list_alerts_for_repo.go @@ -0,0 +1,140 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_list_alerts_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["tool_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("tool_name=%v", val)) + } + if val, ok := args["tool_guid"]; ok { + queryParams = append(queryParams, fmt.Sprintf("tool_guid=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["pr"]; ok { + queryParams = append(queryParams, fmt.Sprintf("pr=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["severity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("severity=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_list_alerts_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_alerts", + mcp.WithDescription("List code scanning alerts for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("tool_name", mcp.Description("The name of a code scanning tool. Only results by this tool will be listed. You can specify the tool by using either `tool_name` or `tool_guid`, but not both.")), + mcp.WithString("tool_guid", mcp.Description("The GUID of a code scanning tool. Only results by this tool will be listed. Note that some code scanning tools may not include a GUID in their analysis data. You can specify the tool by using either `tool_guid` or `tool_name`, but not both.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("ref", mcp.Description("The Git reference for the results you want to list. The `ref` for a branch can be formatted either as `refs/heads/` or simply ``. To reference a pull request use `refs/pull//merge`.")), + mcp.WithNumber("pr", mcp.Description("The number of the pull request for the results you want to list.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.")), + mcp.WithString("state", mcp.Description("If specified, only code scanning alerts with this state will be returned.")), + mcp.WithString("severity", mcp.Description("If specified, only code scanning alerts with this severity will be returned.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_list_alerts_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_list_codeql_databases.go b/MCP/tools/code_scanning/code_scanning_list_codeql_databases.go new file mode 100644 index 0000000..1019f9e --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_list_codeql_databases.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_list_codeql_databasesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/codeql/databases", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_list_codeql_databasesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_codeql_databases", + mcp.WithDescription("List CodeQL databases for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_list_codeql_databasesHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_list_recent_analyses.go b/MCP/tools/code_scanning/code_scanning_list_recent_analyses.go new file mode 100644 index 0000000..7c9226d --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_list_recent_analyses.go @@ -0,0 +1,128 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_list_recent_analysesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["tool_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("tool_name=%v", val)) + } + if val, ok := args["tool_guid"]; ok { + queryParams = append(queryParams, fmt.Sprintf("tool_guid=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["pr"]; ok { + queryParams = append(queryParams, fmt.Sprintf("pr=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["sarif_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sarif_id=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/analyses%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_list_recent_analysesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-scanning_analyses", + mcp.WithDescription("List code scanning analyses for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("tool_name", mcp.Description("The name of a code scanning tool. Only results by this tool will be listed. You can specify the tool by using either `tool_name` or `tool_guid`, but not both.")), + mcp.WithString("tool_guid", mcp.Description("The GUID of a code scanning tool. Only results by this tool will be listed. Note that some code scanning tools may not include a GUID in their analysis data. You can specify the tool by using either `tool_guid` or `tool_name`, but not both.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("pr", mcp.Description("The number of the pull request for the results you want to list.")), + mcp.WithString("ref", mcp.Description("The Git reference for the analyses you want to list. The `ref` for a branch can be formatted either as `refs/heads/` or simply ``. To reference a pull request use `refs/pull//merge`.")), + mcp.WithString("sarif_id", mcp.Description("Filter analyses belonging to the same SARIF upload.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_list_recent_analysesHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_update_alert.go b/MCP/tools/code_scanning/code_scanning_update_alert.go new file mode 100644 index 0000000..6e55b2e --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_update_alert.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_update_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/alerts/%s", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_update_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_code-scanning_alerts_alert_number", + mcp.WithDescription("Update a code scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + mcp.WithBoolean("create_request", mcp.Description("Input parameter: If `true`, attempt to create an alert dismissal request.")), + mcp.WithString("dismissed_comment", mcp.Description("Input parameter: The dismissal comment associated with the dismissal of the alert.")), + mcp.WithString("dismissed_reason", mcp.Description("Input parameter: **Required when the state is dismissed.** The reason for dismissing or closing the alert.")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: Sets the state of the code scanning alert. You must provide `dismissed_reason` when you set the state to `dismissed`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_update_alertHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_update_default_setup.go b/MCP/tools/code_scanning/code_scanning_update_default_setup.go new file mode 100644 index 0000000..1917033 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_update_default_setup.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_update_default_setupHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/default-setup", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_update_default_setupTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_code-scanning_default-setup", + mcp.WithDescription("Update a code scanning default setup configuration"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("languages", mcp.Description("Input parameter: CodeQL languages to be analyzed.")), + mcp.WithString("query_suite", mcp.Description("Input parameter: CodeQL query suite to be used.")), + mcp.WithString("runner_label", mcp.Description("Input parameter: Runner label to be used if the runner type is labeled.")), + mcp.WithString("runner_type", mcp.Description("Input parameter: Runner type to be used.")), + mcp.WithString("state", mcp.Description("Input parameter: The desired state of code scanning default setup.")), + mcp.WithString("threat_model", mcp.Description("Input parameter: Threat model to be used for code scanning analysis. Use `remote` to analyze only network sources and `remote_and_local` to include local sources like filesystem access, command-line arguments, database reads, environment variable and standard input.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_update_default_setupHandler(cfg), + } +} diff --git a/MCP/tools/code_scanning/code_scanning_upload_sarif.go b/MCP/tools/code_scanning/code_scanning_upload_sarif.go new file mode 100644 index 0000000..c832418 --- /dev/null +++ b/MCP/tools/code_scanning/code_scanning_upload_sarif.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_scanning_upload_sarifHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-scanning/sarifs", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_scanning_upload_sarifTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_code-scanning_sarifs", + mcp.WithDescription("Upload an analysis as SARIF data"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("Input parameter: The full Git reference, formatted as `refs/heads/`,\n`refs/tags/`, `refs/pull//merge`, or `refs/pull//head`.")), + mcp.WithString("sarif", mcp.Required(), mcp.Description("Input parameter: A Base64 string representing the SARIF file to upload. You must first compress your SARIF file using [`gzip`](http://www.gnu.org/software/gzip/manual/gzip.html) and then translate the contents of the file into a Base64 encoding string. For more information, see \"[SARIF support for code scanning](https://docs.github.com/code-security/secure-coding/sarif-support-for-code-scanning).\"")), + mcp.WithString("started_at", mcp.Description("Input parameter: The time that the analysis run began. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("tool_name", mcp.Description("Input parameter: The name of the tool used to generate the code scanning analysis. If this parameter is not used, the tool name defaults to \"API\". If the uploaded SARIF contains a tool GUID, this will be available for filtering using the `tool_guid` parameter of operations such as `GET /repos/{owner}/{repo}/code-scanning/alerts`.")), + mcp.WithBoolean("validate", mcp.Description("Input parameter: Whether the SARIF file will be validated according to the code scanning specifications.\nThis parameter is intended to help integrators ensure that the uploaded SARIF files are correctly rendered by code scanning.")), + mcp.WithString("checkout_uri", mcp.Description("Input parameter: The base directory used in the analysis, as it appears in the SARIF file.\nThis property is used to convert file paths from absolute to relative, so that alerts can be mapped to their correct location in the repository.")), + mcp.WithString("commit_sha", mcp.Required(), mcp.Description("Input parameter: The SHA of the commit to which the analysis you are uploading relates.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_scanning_upload_sarifHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_attach_configuration.go b/MCP/tools/code_security/code_security_attach_configuration.go new file mode 100644 index 0000000..979db02 --- /dev/null +++ b/MCP/tools/code_security/code_security_attach_configuration.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_attach_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/%s/attach", cfg.BaseURL, org, configuration_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_attach_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_code-security_configurations_configuration_id_attach", + mcp.WithDescription("Attach a configuration to repositories"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithString("scope", mcp.Required(), mcp.Description("Input parameter: The type of repositories to attach the configuration to. `selected` means the configuration will be attached to only the repositories specified by `selected_repository_ids`")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository IDs to attach the configuration to. You can only provide a list of repository ids when the `scope` is set to `selected`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_attach_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_attach_enterprise_configuration.go b/MCP/tools/code_security/code_security_attach_enterprise_configuration.go new file mode 100644 index 0000000..a9a10e4 --- /dev/null +++ b/MCP/tools/code_security/code_security_attach_enterprise_configuration.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_attach_enterprise_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/%s/attach", cfg.BaseURL, enterprise, configuration_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_attach_enterprise_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_enterprises_enterprise_code-security_configurations_configuration_id_attach", + mcp.WithDescription("Attach an enterprise configuration to repositories"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithString("scope", mcp.Required(), mcp.Description("Input parameter: The type of repositories to attach the configuration to.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_attach_enterprise_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_create_configuration.go b/MCP/tools/code_security/code_security_create_configuration.go new file mode 100644 index 0000000..dec52ab --- /dev/null +++ b/MCP/tools/code_security/code_security_create_configuration.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_create_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_create_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_code-security_configurations", + mcp.WithDescription("Create a code security configuration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("code_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of code scanning delegated alert dismissal")), + mcp.WithString("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithObject("secret_scanning_delegated_bypass_options", mcp.Description("Input parameter: Feature options for secret scanning delegated bypass")), + mcp.WithString("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("secret_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of secret scanning delegated alert dismissal")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non provider patterns")), + mcp.WithString("advanced_security", mcp.Description("Input parameter: The enablement status of GitHub Advanced Security features. `enabled` will enable both Code Security and Secret Protection features.")), + mcp.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement status for a security configuration")), + mcp.WithString("private_vulnerability_reporting", mcp.Description("Input parameter: The enablement status of private vulnerability reporting")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + mcp.WithString("secret_scanning_generic_secrets", mcp.Description("Input parameter: The enablement status of Copilot secret scanning")), + mcp.WithString("secret_scanning_push_protection", mcp.Description("Input parameter: The enablement status of secret scanning push protection")), + mcp.WithString("code_scanning_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + mcp.WithString("dependency_graph", mcp.Description("Input parameter: The enablement status of Dependency Graph")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the code security configuration. Must be unique within the organization.")), + mcp.WithString("secret_scanning_delegated_bypass", mcp.Description("Input parameter: The enablement status of secret scanning delegated bypass")), + mcp.WithString("description", mcp.Required(), mcp.Description("Input parameter: A description of the code security configuration")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_create_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_create_configuration_for_enterprise.go b/MCP/tools/code_security/code_security_create_configuration_for_enterprise.go new file mode 100644 index 0000000..5fead48 --- /dev/null +++ b/MCP/tools/code_security/code_security_create_configuration_for_enterprise.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_create_configuration_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations", cfg.BaseURL, enterprise) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_create_configuration_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_enterprises_enterprise_code-security_configurations", + mcp.WithDescription("Create a code security configuration for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non provider patterns")), + mcp.WithString("code_scanning_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + mcp.WithString("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the code security configuration. Must be unique within the enterprise.")), + mcp.WithString("code_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of code scanning delegated alert dismissal")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithString("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("advanced_security", mcp.Description("Input parameter: The enablement status of GitHub Advanced Security features. `enabled` will enable both Code Security and Secret Protection features.")), + mcp.WithString("dependency_graph", mcp.Description("Input parameter: The enablement status of Dependency Graph")), + mcp.WithString("secret_scanning_push_protection", mcp.Description("Input parameter: The enablement status of secret scanning push protection")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("secret_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of secret scanning delegated alert dismissal")), + mcp.WithString("description", mcp.Required(), mcp.Description("Input parameter: A description of the code security configuration")), + mcp.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement status for a security configuration")), + mcp.WithString("secret_scanning_generic_secrets", mcp.Description("Input parameter: The enablement status of Copilot secret scanning")), + mcp.WithString("private_vulnerability_reporting", mcp.Description("Input parameter: The enablement status of private vulnerability reporting")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_create_configuration_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_delete_configuration.go b/MCP/tools/code_security/code_security_delete_configuration.go new file mode 100644 index 0000000..377cb1b --- /dev/null +++ b/MCP/tools/code_security/code_security_delete_configuration.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_delete_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/%s", cfg.BaseURL, org, configuration_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_delete_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_code-security_configurations_configuration_id", + mcp.WithDescription("Delete a code security configuration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_delete_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_delete_configuration_for_enterprise.go b/MCP/tools/code_security/code_security_delete_configuration_for_enterprise.go new file mode 100644 index 0000000..88f2bfe --- /dev/null +++ b/MCP/tools/code_security/code_security_delete_configuration_for_enterprise.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_delete_configuration_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/%s", cfg.BaseURL, enterprise, configuration_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_delete_configuration_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_enterprises_enterprise_code-security_configurations_configuration_id", + mcp.WithDescription("Delete a code security configuration for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_delete_configuration_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_detach_configuration.go b/MCP/tools/code_security/code_security_detach_configuration.go new file mode 100644 index 0000000..346e725 --- /dev/null +++ b/MCP/tools/code_security/code_security_detach_configuration.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_detach_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/detach", cfg.BaseURL, org) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_detach_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_code-security_configurations_detach", + mcp.WithDescription("Detach configurations from repositories"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository IDs to detach from configurations.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_detach_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_configuration.go b/MCP/tools/code_security/code_security_get_configuration.go new file mode 100644 index 0000000..b0f0c90 --- /dev/null +++ b/MCP/tools/code_security/code_security_get_configuration.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/%s", cfg.BaseURL, org, configuration_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_code-security_configurations_configuration_id", + mcp.WithDescription("Get a code security configuration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_configuration_for_repository.go b/MCP/tools/code_security/code_security_get_configuration_for_repository.go new file mode 100644 index 0000000..fbaf365 --- /dev/null +++ b/MCP/tools/code_security/code_security_get_configuration_for_repository.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_configuration_for_repositoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/code-security-configuration", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_configuration_for_repositoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_code-security-configuration", + mcp.WithDescription("Get the code security configuration associated with a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_configuration_for_repositoryHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_configurations_for_enterprise.go b/MCP/tools/code_security/code_security_get_configurations_for_enterprise.go new file mode 100644 index 0000000..dde8c9e --- /dev/null +++ b/MCP/tools/code_security/code_security_get_configurations_for_enterprise.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_configurations_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations%s", cfg.BaseURL, enterprise, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_configurations_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_enterprises_enterprise_code-security_configurations", + mcp.WithDescription("Get code security configurations for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_configurations_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_configurations_for_org.go b/MCP/tools/code_security/code_security_get_configurations_for_org.go new file mode 100644 index 0000000..85ad65d --- /dev/null +++ b/MCP/tools/code_security/code_security_get_configurations_for_org.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_configurations_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["target_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("target_type=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_configurations_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_code-security_configurations", + mcp.WithDescription("Get code security configurations for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("target_type", mcp.Description("The target type of the code security configuration")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_configurations_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_default_configurations.go b/MCP/tools/code_security/code_security_get_default_configurations.go new file mode 100644 index 0000000..7cef3fe --- /dev/null +++ b/MCP/tools/code_security/code_security_get_default_configurations.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_default_configurationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/defaults", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_default_configurationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_code-security_configurations_defaults", + mcp.WithDescription("Get default code security configurations"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_default_configurationsHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_default_configurations_for_enterprise.go b/MCP/tools/code_security/code_security_get_default_configurations_for_enterprise.go new file mode 100644 index 0000000..bf55cc1 --- /dev/null +++ b/MCP/tools/code_security/code_security_get_default_configurations_for_enterprise.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_default_configurations_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/defaults", cfg.BaseURL, enterprise) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_default_configurations_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_enterprises_enterprise_code-security_configurations_defaults", + mcp.WithDescription("Get default code security configurations for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_default_configurations_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_repositories_for_configuration.go b/MCP/tools/code_security/code_security_get_repositories_for_configuration.go new file mode 100644 index 0000000..027a07a --- /dev/null +++ b/MCP/tools/code_security/code_security_get_repositories_for_configuration.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_repositories_for_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["status"]; ok { + queryParams = append(queryParams, fmt.Sprintf("status=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/%s/repositories%s", cfg.BaseURL, org, configuration_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_repositories_for_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_code-security_configurations_configuration_id_repositories", + mcp.WithDescription("Get repositories associated with a code security configuration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("status", mcp.Description("A comma-separated list of statuses. If specified, only repositories with these attachment statuses will be returned.\n\nCan be: `all`, `attached`, `attaching`, `detached`, `removed`, `enforced`, `failed`, `updating`, `removed_by_enterprise`")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_repositories_for_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_repositories_for_enterprise_configuration.go b/MCP/tools/code_security/code_security_get_repositories_for_enterprise_configuration.go new file mode 100644 index 0000000..e4de7ab --- /dev/null +++ b/MCP/tools/code_security/code_security_get_repositories_for_enterprise_configuration.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_repositories_for_enterprise_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["status"]; ok { + queryParams = append(queryParams, fmt.Sprintf("status=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/%s/repositories%s", cfg.BaseURL, enterprise, configuration_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_repositories_for_enterprise_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_enterprises_enterprise_code-security_configurations_configuration_id_repositories", + mcp.WithDescription("Get repositories associated with an enterprise code security configuration"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("status", mcp.Description("A comma-separated list of statuses. If specified, only repositories with these attachment statuses will be returned.\n\nCan be: `all`, `attached`, `attaching`, `removed`, `enforced`, `failed`, `updating`, `removed_by_enterprise`")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_repositories_for_enterprise_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_get_single_configuration_for_enterprise.go b/MCP/tools/code_security/code_security_get_single_configuration_for_enterprise.go new file mode 100644 index 0000000..f5373c0 --- /dev/null +++ b/MCP/tools/code_security/code_security_get_single_configuration_for_enterprise.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_get_single_configuration_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/%s", cfg.BaseURL, enterprise, configuration_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_get_single_configuration_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_enterprises_enterprise_code-security_configurations_configuration_id", + mcp.WithDescription("Retrieve a code security configuration of an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_get_single_configuration_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_set_configuration_as_default.go b/MCP/tools/code_security/code_security_set_configuration_as_default.go new file mode 100644 index 0000000..8f0da21 --- /dev/null +++ b/MCP/tools/code_security/code_security_set_configuration_as_default.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_set_configuration_as_defaultHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/%s/defaults", cfg.BaseURL, org, configuration_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_set_configuration_as_defaultTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_code-security_configurations_configuration_id_defaults", + mcp.WithDescription("Set a code security configuration as a default for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithString("default_for_new_repos", mcp.Description("Input parameter: Specify which types of repository this security configuration should be applied to by default.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_set_configuration_as_defaultHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_set_configuration_as_default_for_enterprise.go b/MCP/tools/code_security/code_security_set_configuration_as_default_for_enterprise.go new file mode 100644 index 0000000..f580988 --- /dev/null +++ b/MCP/tools/code_security/code_security_set_configuration_as_default_for_enterprise.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_set_configuration_as_default_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/%s/defaults", cfg.BaseURL, enterprise, configuration_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_set_configuration_as_default_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_enterprises_enterprise_code-security_configurations_configuration_id_defaults", + mcp.WithDescription("Set a code security configuration as a default for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithString("default_for_new_repos", mcp.Description("Input parameter: Specify which types of repository this security configuration should be applied to by default.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_set_configuration_as_default_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_update_configuration.go b/MCP/tools/code_security/code_security_update_configuration.go new file mode 100644 index 0000000..7c5fdf4 --- /dev/null +++ b/MCP/tools/code_security/code_security_update_configuration.go @@ -0,0 +1,125 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_update_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/code-security/configurations/%s", cfg.BaseURL, org, configuration_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_update_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_code-security_configurations_configuration_id", + mcp.WithDescription("Update a code security configuration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithString("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + mcp.WithString("secret_scanning_push_protection", mcp.Description("Input parameter: The enablement status of secret scanning push protection")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithString("dependency_graph", mcp.Description("Input parameter: The enablement status of Dependency Graph")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non-provider patterns")), + mcp.WithString("code_scanning_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + mcp.WithObject("secret_scanning_delegated_bypass_options", mcp.Description("Input parameter: Feature options for secret scanning delegated bypass")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + mcp.WithString("secret_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of secret scanning delegated alert dismissal")), + mcp.WithString("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("secret_scanning_delegated_bypass", mcp.Description("Input parameter: The enablement status of secret scanning delegated bypass")), + mcp.WithString("secret_scanning_generic_secrets", mcp.Description("Input parameter: The enablement status of Copilot secret scanning")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement status for a security configuration")), + mcp.WithString("code_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of code scanning delegated alert dismissal")), + mcp.WithString("private_vulnerability_reporting", mcp.Description("Input parameter: The enablement status of private vulnerability reporting")), + mcp.WithString("advanced_security", mcp.Description("Input parameter: The enablement status of GitHub Advanced Security features. `enabled` will enable both Code Security and Secret Protection features.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the code security configuration. Must be unique within the organization.")), + mcp.WithString("description", mcp.Description("Input parameter: A description of the code security configuration")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_update_configurationHandler(cfg), + } +} diff --git a/MCP/tools/code_security/code_security_update_enterprise_configuration.go b/MCP/tools/code_security/code_security_update_enterprise_configuration.go new file mode 100644 index 0000000..060404f --- /dev/null +++ b/MCP/tools/code_security/code_security_update_enterprise_configuration.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Code_security_update_enterprise_configurationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + configuration_idVal, ok := args["configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: configuration_id"), nil + } + configuration_id, ok := configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/enterprises/%s/code-security/configurations/%s", cfg.BaseURL, enterprise, configuration_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCode_security_update_enterprise_configurationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_enterprises_enterprise_code-security_configurations_configuration_id", + mcp.WithDescription("Update a custom code security configuration for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithNumber("configuration_id", mcp.Required(), mcp.Description("The unique identifier of the code security configuration.")), + mcp.WithString("secret_scanning_generic_secrets", mcp.Description("Input parameter: The enablement status of Copilot secret scanning")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the code security configuration. Must be unique across the enterprise.")), + mcp.WithString("secret_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of secret scanning delegated alert dismissal")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non-provider patterns")), + mcp.WithString("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + mcp.WithString("dependency_graph", mcp.Description("Input parameter: The enablement status of Dependency Graph")), + mcp.WithString("description", mcp.Description("Input parameter: A description of the code security configuration")), + mcp.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement status for a security configuration")), + mcp.WithString("code_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of code scanning delegated alert dismissal")), + mcp.WithString("secret_scanning_push_protection", mcp.Description("Input parameter: The enablement status of secret scanning push protection")), + mcp.WithString("advanced_security", mcp.Description("Input parameter: The enablement status of GitHub Advanced Security features. `enabled` will enable both Code Security and Secret Protection features.")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithString("private_vulnerability_reporting", mcp.Description("Input parameter: The enablement status of private vulnerability reporting")), + mcp.WithString("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + mcp.WithString("code_scanning_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + ) + + return models.Tool{ + Definition: tool, + Handler: Code_security_update_enterprise_configurationHandler(cfg), + } +} diff --git a/MCP/tools/codes_of_conduct/codes_of_conduct_get_all_codes_of_conduct.go b/MCP/tools/codes_of_conduct/codes_of_conduct_get_all_codes_of_conduct.go new file mode 100644 index 0000000..5f7debc --- /dev/null +++ b/MCP/tools/codes_of_conduct/codes_of_conduct_get_all_codes_of_conduct.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codes_of_conduct_get_all_codes_of_conductHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/codes_of_conduct", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodes_of_conduct_get_all_codes_of_conductTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_codes_of_conduct", + mcp.WithDescription("Get all codes of conduct"), + ) + + return models.Tool{ + Definition: tool, + Handler: Codes_of_conduct_get_all_codes_of_conductHandler(cfg), + } +} diff --git a/MCP/tools/codes_of_conduct/codes_of_conduct_get_conduct_code.go b/MCP/tools/codes_of_conduct/codes_of_conduct_get_conduct_code.go new file mode 100644 index 0000000..efd3b24 --- /dev/null +++ b/MCP/tools/codes_of_conduct/codes_of_conduct_get_conduct_code.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codes_of_conduct_get_conduct_codeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + keyVal, ok := args["key"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: key"), nil + } + key, ok := keyVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: key"), nil + } + url := fmt.Sprintf("%s/codes_of_conduct/%s", cfg.BaseURL, key) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodes_of_conduct_get_conduct_codeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_codes_of_conduct_key", + mcp.WithDescription("Get a code of conduct"), + mcp.WithString("key", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codes_of_conduct_get_conduct_codeHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_add_repository_for_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_add_repository_for_secret_for_authenticated_user.go new file mode 100644 index 0000000..755f466 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_add_repository_for_secret_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_add_repository_for_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s/repositories/%s", cfg.BaseURL, secret_name, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_add_repository_for_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_codespaces_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Add a selected repository to a user secret"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_add_repository_for_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_add_selected_repo_to_org_secret.go b/MCP/tools/codespaces/codespaces_add_selected_repo_to_org_secret.go new file mode 100644 index 0000000..c63853d --- /dev/null +++ b/MCP/tools/codespaces/codespaces_add_selected_repo_to_org_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_add_selected_repo_to_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s/repositories/%s", cfg.BaseURL, org, secret_name, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_add_selected_repo_to_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_codespaces_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Add selected repository to an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_add_selected_repo_to_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_check_permissions_for_devcontainer.go b/MCP/tools/codespaces/codespaces_check_permissions_for_devcontainer.go new file mode 100644 index 0000000..cd7740d --- /dev/null +++ b/MCP/tools/codespaces/codespaces_check_permissions_for_devcontainer.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_check_permissions_for_devcontainerHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["devcontainer_path"]; ok { + queryParams = append(queryParams, fmt.Sprintf("devcontainer_path=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/permissions_check%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_check_permissions_for_devcontainerTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_permissions_check", + mcp.WithDescription("Check if permissions defined by a devcontainer have been accepted by the authenticated user"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The git reference that points to the location of the devcontainer configuration to use for the permission check. The value of `ref` will typically be a branch name (`heads/BRANCH_NAME`). For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + mcp.WithString("devcontainer_path", mcp.Required(), mcp.Description("Path to the devcontainer.json configuration to use for the permission check.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_check_permissions_for_devcontainerHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_codespace_machines_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_codespace_machines_for_authenticated_user.go new file mode 100644 index 0000000..c894c03 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_codespace_machines_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_codespace_machines_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s/machines", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_codespace_machines_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_codespace_name_machines", + mcp.WithDescription("List machine types for a codespace"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_codespace_machines_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_create_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_create_for_authenticated_user.go new file mode 100644 index 0000000..cb07664 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_create_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_create_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/codespaces", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_create_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_codespaces", + mcp.WithDescription("Create a codespace for the authenticated user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_create_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_create_or_update_org_secret.go b/MCP/tools/codespaces/codespaces_create_or_update_org_secret.go new file mode 100644 index 0000000..28735c7 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_create_or_update_org_secret.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_create_or_update_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_create_or_update_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_codespaces_secrets_secret_name", + mcp.WithDescription("Create or update an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("encrypted_value", mcp.Description("Input parameter: The value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get an organization public key](https://docs.github.com/rest/codespaces/organization-secrets#get-an-organization-public-key) endpoint.")), + mcp.WithString("key_id", mcp.Description("Input parameter: The ID of the key you used to encrypt the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository IDs that can access the organization secret. You can only provide a list of repository IDs when the `visibility` is set to `selected`. You can manage the list of selected repositories using the [List selected repositories for an organization secret](https://docs.github.com/rest/codespaces/organization-secrets#list-selected-repositories-for-an-organization-secret), [Set selected repositories for an organization secret](https://docs.github.com/rest/codespaces/organization-secrets#set-selected-repositories-for-an-organization-secret), and [Remove selected repository from an organization secret](https://docs.github.com/rest/codespaces/organization-secrets#remove-selected-repository-from-an-organization-secret) endpoints.")), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: Which type of organization repositories have access to the organization secret. `selected` means only the repositories specified by `selected_repository_ids` can access the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_create_or_update_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_create_or_update_repo_secret.go b/MCP/tools/codespaces/codespaces_create_or_update_repo_secret.go new file mode 100644 index 0000000..4ec4cf0 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_create_or_update_repo_secret.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_create_or_update_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_create_or_update_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_codespaces_secrets_secret_name", + mcp.WithDescription("Create or update a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("encrypted_value", mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get a repository public key](https://docs.github.com/rest/codespaces/repository-secrets#get-a-repository-public-key) endpoint.")), + mcp.WithString("key_id", mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_create_or_update_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_create_or_update_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_create_or_update_secret_for_authenticated_user.go new file mode 100644 index 0000000..1bb09f4 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_create_or_update_secret_for_authenticated_user.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_create_or_update_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s", cfg.BaseURL, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_create_or_update_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_codespaces_secrets_secret_name", + mcp.WithDescription("Create or update a secret for the authenticated user"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("encrypted_value", mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get the public key for the authenticated user](https://docs.github.com/rest/codespaces/secrets#get-public-key-for-the-authenticated-user) endpoint.")), + mcp.WithString("key_id", mcp.Required(), mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository ids that can access the user secret. You can manage the list of selected repositories using the [List selected repositories for a user secret](https://docs.github.com/rest/codespaces/secrets#list-selected-repositories-for-a-user-secret), [Set selected repositories for a user secret](https://docs.github.com/rest/codespaces/secrets#set-selected-repositories-for-a-user-secret), and [Remove a selected repository from a user secret](https://docs.github.com/rest/codespaces/secrets#remove-a-selected-repository-from-a-user-secret) endpoints.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_create_or_update_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_create_with_pr_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_create_with_pr_for_authenticated_user.go new file mode 100644 index 0000000..cbe83f5 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_create_with_pr_for_authenticated_user.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_create_with_pr_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/codespaces", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_create_with_pr_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_pull_number_codespaces", + mcp.WithDescription("Create a codespace from a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithString("devcontainer_path", mcp.Description("Input parameter: Path to devcontainer.json config to use for this codespace")), + mcp.WithString("display_name", mcp.Description("Input parameter: Display name for this codespace")), + mcp.WithString("geo", mcp.Description("Input parameter: The geographic area for this codespace. If not specified, the value is assigned by IP. This property replaces `location`, which is closing down.")), + mcp.WithString("client_ip", mcp.Description("Input parameter: IP for location auto-detection when proxying a request")), + mcp.WithNumber("idle_timeout_minutes", mcp.Description("Input parameter: Time in minutes before codespace stops from inactivity")), + mcp.WithNumber("retention_period_minutes", mcp.Description("Input parameter: Duration in minutes after codespace has gone idle in which it will be deleted. Must be integer minutes between 0 and 43200 (30 days).")), + mcp.WithBoolean("multi_repo_permissions_opt_out", mcp.Description("Input parameter: Whether to authorize requested permissions from devcontainer.json")), + mcp.WithString("location", mcp.Description("Input parameter: The requested location for a new codespace. Best efforts are made to respect this upon creation. Assigned by IP if not provided.")), + mcp.WithString("machine", mcp.Description("Input parameter: Machine type to use for this codespace")), + mcp.WithString("working_directory", mcp.Description("Input parameter: Working directory for this codespace")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_create_with_pr_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_create_with_repo_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_create_with_repo_for_authenticated_user.go new file mode 100644 index 0000000..936f062 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_create_with_repo_for_authenticated_user.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_create_with_repo_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_create_with_repo_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_codespaces", + mcp.WithDescription("Create a codespace in a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("machine", mcp.Description("Input parameter: Machine type to use for this codespace")), + mcp.WithString("working_directory", mcp.Description("Input parameter: Working directory for this codespace")), + mcp.WithString("geo", mcp.Description("Input parameter: The geographic area for this codespace. If not specified, the value is assigned by IP. This property replaces `location`, which is closing down.")), + mcp.WithString("ref", mcp.Description("Input parameter: Git ref (typically a branch name) for this codespace")), + mcp.WithString("devcontainer_path", mcp.Description("Input parameter: Path to devcontainer.json config to use for this codespace")), + mcp.WithString("display_name", mcp.Description("Input parameter: Display name for this codespace")), + mcp.WithBoolean("multi_repo_permissions_opt_out", mcp.Description("Input parameter: Whether to authorize requested permissions from devcontainer.json")), + mcp.WithNumber("retention_period_minutes", mcp.Description("Input parameter: Duration in minutes after codespace has gone idle in which it will be deleted. Must be integer minutes between 0 and 43200 (30 days).")), + mcp.WithString("client_ip", mcp.Description("Input parameter: IP for location auto-detection when proxying a request")), + mcp.WithNumber("idle_timeout_minutes", mcp.Description("Input parameter: Time in minutes before codespace stops from inactivity")), + mcp.WithString("location", mcp.Description("Input parameter: The requested location for a new codespace. Best efforts are made to respect this upon creation. Assigned by IP if not provided.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_create_with_repo_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_delete_codespaces_access_users.go b/MCP/tools/codespaces/codespaces_delete_codespaces_access_users.go new file mode 100644 index 0000000..a987d8a --- /dev/null +++ b/MCP/tools/codespaces/codespaces_delete_codespaces_access_users.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_delete_codespaces_access_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/access/selected_users", cfg.BaseURL, org) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_delete_codespaces_access_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_codespaces_access_selected_users", + mcp.WithDescription("Remove users from Codespaces access for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_usernames", mcp.Required(), mcp.Description("Input parameter: The usernames of the organization members whose codespaces should not be billed to the organization.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_delete_codespaces_access_usersHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_delete_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_delete_for_authenticated_user.go new file mode 100644 index 0000000..6bcb376 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_delete_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_delete_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_delete_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_codespaces_codespace_name", + mcp.WithDescription("Delete a codespace for the authenticated user"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_delete_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_delete_from_organization.go b/MCP/tools/codespaces/codespaces_delete_from_organization.go new file mode 100644 index 0000000..d5558da --- /dev/null +++ b/MCP/tools/codespaces/codespaces_delete_from_organization.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_delete_from_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/members/%s/codespaces/%s", cfg.BaseURL, org, username, codespace_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_delete_from_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_members_username_codespaces_codespace_name", + mcp.WithDescription("Delete a codespace from the organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_delete_from_organizationHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_delete_org_secret.go b/MCP/tools/codespaces/codespaces_delete_org_secret.go new file mode 100644 index 0000000..1b5b872 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_delete_org_secret.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_delete_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_delete_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_codespaces_secrets_secret_name", + mcp.WithDescription("Delete an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_delete_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_delete_repo_secret.go b/MCP/tools/codespaces/codespaces_delete_repo_secret.go new file mode 100644 index 0000000..5e1941e --- /dev/null +++ b/MCP/tools/codespaces/codespaces_delete_repo_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_delete_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_delete_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_codespaces_secrets_secret_name", + mcp.WithDescription("Delete a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_delete_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_delete_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_delete_secret_for_authenticated_user.go new file mode 100644 index 0000000..7003b80 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_delete_secret_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_delete_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s", cfg.BaseURL, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_delete_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_codespaces_secrets_secret_name", + mcp.WithDescription("Delete a secret for the authenticated user"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_delete_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_export_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_export_for_authenticated_user.go new file mode 100644 index 0000000..e69e5a7 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_export_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_export_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s/exports", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_export_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_codespaces_codespace_name_exports", + mcp.WithDescription("Export a codespace for the authenticated user"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_export_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_codespaces_for_user_in_org.go b/MCP/tools/codespaces/codespaces_get_codespaces_for_user_in_org.go new file mode 100644 index 0000000..60d2ba0 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_codespaces_for_user_in_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_codespaces_for_user_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/members/%s/codespaces%s", cfg.BaseURL, org, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_codespaces_for_user_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_members_username_codespaces", + mcp.WithDescription("List codespaces for a user in organization"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_codespaces_for_user_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_export_details_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_get_export_details_for_authenticated_user.go new file mode 100644 index 0000000..4146528 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_export_details_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_export_details_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + export_idVal, ok := args["export_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: export_id"), nil + } + export_id, ok := export_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: export_id"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s/exports/%s", cfg.BaseURL, codespace_name, export_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_export_details_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_codespace_name_exports_export_id", + mcp.WithDescription("Get details about a codespace export"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + mcp.WithString("export_id", mcp.Required(), mcp.Description("The ID of the export operation, or `latest`. Currently only `latest` is currently supported.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_export_details_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_get_for_authenticated_user.go new file mode 100644 index 0000000..310607e --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_codespace_name", + mcp.WithDescription("Get a codespace for the authenticated user"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_org_public_key.go b/MCP/tools/codespaces/codespaces_get_org_public_key.go new file mode 100644 index 0000000..4a56e0d --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_org_public_key.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_org_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/public-key", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_org_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_codespaces_secrets_public-key", + mcp.WithDescription("Get an organization public key"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_org_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_org_secret.go b/MCP/tools/codespaces/codespaces_get_org_secret.go new file mode 100644 index 0000000..ea4e5ae --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_org_secret.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_codespaces_secrets_secret_name", + mcp.WithDescription("Get an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_public_key_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_get_public_key_for_authenticated_user.go new file mode 100644 index 0000000..efab2c0 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_public_key_for_authenticated_user.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_public_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/user/codespaces/secrets/public-key", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_public_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_secrets_public-key", + mcp.WithDescription("Get public key for the authenticated user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_public_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_repo_public_key.go b/MCP/tools/codespaces/codespaces_get_repo_public_key.go new file mode 100644 index 0000000..6b011f9 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_repo_public_key.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_repo_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/secrets/public-key", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_repo_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_secrets_public-key", + mcp.WithDescription("Get a repository public key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_repo_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_repo_secret.go b/MCP/tools/codespaces/codespaces_get_repo_secret.go new file mode 100644 index 0000000..dc61255 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_repo_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_secrets_secret_name", + mcp.WithDescription("Get a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_get_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_get_secret_for_authenticated_user.go new file mode 100644 index 0000000..c1ed2d2 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_get_secret_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_get_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s", cfg.BaseURL, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_get_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_secrets_secret_name", + mcp.WithDescription("Get a secret for the authenticated user"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_get_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_devcontainers_in_repository_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_list_devcontainers_in_repository_for_authenticated_user.go new file mode 100644 index 0000000..4d34eca --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_devcontainers_in_repository_for_authenticated_user.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_devcontainers_in_repository_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/devcontainers%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_devcontainers_in_repository_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_devcontainers", + mcp.WithDescription("List devcontainer configurations in a repository for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_devcontainers_in_repository_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_list_for_authenticated_user.go new file mode 100644 index 0000000..1fe900b --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["repository_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("repository_id=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/codespaces%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces", + mcp.WithDescription("List codespaces for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("repository_id", mcp.Description("ID of the Repository to filter on")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_in_organization.go b/MCP/tools/codespaces/codespaces_list_in_organization.go new file mode 100644 index 0000000..190cdfb --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_in_organization.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_in_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/codespaces%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_in_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_codespaces", + mcp.WithDescription("List codespaces for the organization"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_in_organizationHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_in_repository_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_list_in_repository_for_authenticated_user.go new file mode 100644 index 0000000..5ec4100 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_in_repository_for_authenticated_user.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_in_repository_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_in_repository_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces", + mcp.WithDescription("List codespaces in a repository for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_in_repository_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_org_secrets.go b/MCP/tools/codespaces/codespaces_list_org_secrets.go new file mode 100644 index 0000000..0f1275a --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_org_secrets.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_org_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_org_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_codespaces_secrets", + mcp.WithDescription("List organization secrets"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_org_secretsHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_repo_secrets.go b/MCP/tools/codespaces/codespaces_list_repo_secrets.go new file mode 100644 index 0000000..dc2bccf --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_repo_secrets.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_repo_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/secrets%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_repo_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_secrets", + mcp.WithDescription("List repository secrets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_repo_secretsHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_repositories_for_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_list_repositories_for_secret_for_authenticated_user.go new file mode 100644 index 0000000..ab75b4d --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_repositories_for_secret_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_repositories_for_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s/repositories", cfg.BaseURL, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_repositories_for_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_secrets_secret_name_repositories", + mcp.WithDescription("List selected repositories for a user secret"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_repositories_for_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_secrets_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_list_secrets_for_authenticated_user.go new file mode 100644 index 0000000..93a1ea7 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_secrets_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_secrets_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/codespaces/secrets%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_secrets_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_codespaces_secrets", + mcp.WithDescription("List secrets for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_secrets_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_list_selected_repos_for_org_secret.go b/MCP/tools/codespaces/codespaces_list_selected_repos_for_org_secret.go new file mode 100644 index 0000000..6896d41 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_list_selected_repos_for_org_secret.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_list_selected_repos_for_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s/repositories%s", cfg.BaseURL, org, secret_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_list_selected_repos_for_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_codespaces_secrets_secret_name_repositories", + mcp.WithDescription("List selected repositories for an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_list_selected_repos_for_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_pre_flight_with_repo_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_pre_flight_with_repo_for_authenticated_user.go new file mode 100644 index 0000000..ec3fca4 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_pre_flight_with_repo_for_authenticated_user.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_pre_flight_with_repo_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["client_ip"]; ok { + queryParams = append(queryParams, fmt.Sprintf("client_ip=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/new%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_pre_flight_with_repo_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_new", + mcp.WithDescription("Get default attributes for a codespace"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Description("The branch or commit to check for a default devcontainer path. If not specified, the default branch will be checked.")), + mcp.WithString("client_ip", mcp.Description("An alternative IP for default location auto-detection, such as when proxying a request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_pre_flight_with_repo_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_publish_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_publish_for_authenticated_user.go new file mode 100644 index 0000000..0b44a71 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_publish_for_authenticated_user.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_publish_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s/publish", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_publish_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_codespaces_codespace_name_publish", + mcp.WithDescription("Create a repository from an unpublished codespace"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + mcp.WithString("name", mcp.Description("Input parameter: A name for the new repository.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Whether the new repository should be private.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_publish_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_remove_repository_for_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_remove_repository_for_secret_for_authenticated_user.go new file mode 100644 index 0000000..a3da1b6 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_remove_repository_for_secret_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_remove_repository_for_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s/repositories/%s", cfg.BaseURL, secret_name, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_remove_repository_for_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_codespaces_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Remove a selected repository from a user secret"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_remove_repository_for_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_remove_selected_repo_from_org_secret.go b/MCP/tools/codespaces/codespaces_remove_selected_repo_from_org_secret.go new file mode 100644 index 0000000..831ea5a --- /dev/null +++ b/MCP/tools/codespaces/codespaces_remove_selected_repo_from_org_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_remove_selected_repo_from_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s/repositories/%s", cfg.BaseURL, org, secret_name, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_remove_selected_repo_from_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_codespaces_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Remove selected repository from an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_remove_selected_repo_from_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_repo_machines_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_repo_machines_for_authenticated_user.go new file mode 100644 index 0000000..328410d --- /dev/null +++ b/MCP/tools/codespaces/codespaces_repo_machines_for_authenticated_user.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_repo_machines_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["location"]; ok { + queryParams = append(queryParams, fmt.Sprintf("location=%v", val)) + } + if val, ok := args["client_ip"]; ok { + queryParams = append(queryParams, fmt.Sprintf("client_ip=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codespaces/machines%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_repo_machines_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codespaces_machines", + mcp.WithDescription("List available machine types for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("location", mcp.Description("The location to check for available machines. Assigned by IP if not provided.")), + mcp.WithString("client_ip", mcp.Description("IP for location auto-detection when proxying a request")), + mcp.WithString("ref", mcp.Description("The branch or commit to check for prebuild availability and devcontainer restrictions.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_repo_machines_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_set_codespaces_access.go b/MCP/tools/codespaces/codespaces_set_codespaces_access.go new file mode 100644 index 0000000..f0c33ab --- /dev/null +++ b/MCP/tools/codespaces/codespaces_set_codespaces_access.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_set_codespaces_accessHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/access", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_set_codespaces_accessTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_codespaces_access", + mcp.WithDescription("Manage access control for organization codespaces"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_usernames", mcp.Description("Input parameter: The usernames of the organization members who should have access to codespaces in the organization. Required when `visibility` is `selected_members`. The provided list of usernames will replace any existing value.")), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: Which users can access codespaces in the organization. `disabled` means that no users can access codespaces in the organization.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_set_codespaces_accessHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_set_codespaces_access_users.go b/MCP/tools/codespaces/codespaces_set_codespaces_access_users.go new file mode 100644 index 0000000..55fd9a2 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_set_codespaces_access_users.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_set_codespaces_access_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/access/selected_users", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_set_codespaces_access_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_codespaces_access_selected_users", + mcp.WithDescription("Add users to Codespaces access for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_usernames", mcp.Required(), mcp.Description("Input parameter: The usernames of the organization members whose codespaces be billed to the organization.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_set_codespaces_access_usersHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_set_repositories_for_secret_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_set_repositories_for_secret_for_authenticated_user.go new file mode 100644 index 0000000..e0bcf2f --- /dev/null +++ b/MCP/tools/codespaces/codespaces_set_repositories_for_secret_for_authenticated_user.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_set_repositories_for_secret_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/codespaces/secrets/%s/repositories", cfg.BaseURL, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_set_repositories_for_secret_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_codespaces_secrets_secret_name_repositories", + mcp.WithDescription("Set selected repositories for a user secret"), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: An array of repository ids for which a codespace can access the secret. You can manage the list of selected repositories using the [List selected repositories for a user secret](https://docs.github.com/rest/codespaces/secrets#list-selected-repositories-for-a-user-secret), [Add a selected repository to a user secret](https://docs.github.com/rest/codespaces/secrets#add-a-selected-repository-to-a-user-secret), and [Remove a selected repository from a user secret](https://docs.github.com/rest/codespaces/secrets#remove-a-selected-repository-from-a-user-secret) endpoints.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_set_repositories_for_secret_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_set_selected_repos_for_org_secret.go b/MCP/tools/codespaces/codespaces_set_selected_repos_for_org_secret.go new file mode 100644 index 0000000..12fd254 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_set_selected_repos_for_org_secret.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_set_selected_repos_for_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/codespaces/secrets/%s/repositories", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_set_selected_repos_for_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_codespaces_secrets_secret_name_repositories", + mcp.WithDescription("Set selected repositories for an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: An array of repository ids that can access the organization secret. You can only provide a list of repository ids when the `visibility` is set to `selected`. You can add and remove individual repositories using the [Set selected repositories for an organization secret](https://docs.github.com/rest/codespaces/organization-secrets#set-selected-repositories-for-an-organization-secret) and [Remove selected repository from an organization secret](https://docs.github.com/rest/codespaces/organization-secrets#remove-selected-repository-from-an-organization-secret) endpoints.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_set_selected_repos_for_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_start_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_start_for_authenticated_user.go new file mode 100644 index 0000000..8d5cb34 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_start_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_start_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s/start", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_start_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_codespaces_codespace_name_start", + mcp.WithDescription("Start a codespace for the authenticated user"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_start_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_stop_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_stop_for_authenticated_user.go new file mode 100644 index 0000000..8558ea7 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_stop_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_stop_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s/stop", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_stop_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_codespaces_codespace_name_stop", + mcp.WithDescription("Stop a codespace for the authenticated user"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_stop_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_stop_in_organization.go b/MCP/tools/codespaces/codespaces_stop_in_organization.go new file mode 100644 index 0000000..1e1806a --- /dev/null +++ b/MCP/tools/codespaces/codespaces_stop_in_organization.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_stop_in_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/members/%s/codespaces/%s/stop", cfg.BaseURL, org, username, codespace_name) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_stop_in_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_members_username_codespaces_codespace_name_stop", + mcp.WithDescription("Stop a codespace for an organization user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_stop_in_organizationHandler(cfg), + } +} diff --git a/MCP/tools/codespaces/codespaces_update_for_authenticated_user.go b/MCP/tools/codespaces/codespaces_update_for_authenticated_user.go new file mode 100644 index 0000000..b39d522 --- /dev/null +++ b/MCP/tools/codespaces/codespaces_update_for_authenticated_user.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Codespaces_update_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + codespace_nameVal, ok := args["codespace_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: codespace_name"), nil + } + codespace_name, ok := codespace_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: codespace_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/codespaces/%s", cfg.BaseURL, codespace_name) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Codespace + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCodespaces_update_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_user_codespaces_codespace_name", + mcp.WithDescription("Update a codespace for the authenticated user"), + mcp.WithString("codespace_name", mcp.Required(), mcp.Description("The name of the codespace.")), + mcp.WithString("machine", mcp.Description("Input parameter: A valid machine to transition this codespace to.")), + mcp.WithArray("recent_folders", mcp.Description("Input parameter: Recently opened folders inside the codespace. It is currently used by the clients to determine the folder path to load the codespace in.")), + mcp.WithString("display_name", mcp.Description("Input parameter: Display name for this codespace")), + ) + + return models.Tool{ + Definition: tool, + Handler: Codespaces_update_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_add_copilot_seats_for_teams.go b/MCP/tools/copilot/copilot_add_copilot_seats_for_teams.go new file mode 100644 index 0000000..6786d89 --- /dev/null +++ b/MCP/tools/copilot/copilot_add_copilot_seats_for_teams.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_add_copilot_seats_for_teamsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/copilot/billing/selected_teams", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_add_copilot_seats_for_teamsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_copilot_billing_selected_teams", + mcp.WithDescription("Add teams to the Copilot subscription for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_teams", mcp.Required(), mcp.Description("Input parameter: List of team names within the organization to which to grant access to GitHub Copilot.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_add_copilot_seats_for_teamsHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_add_copilot_seats_for_users.go b/MCP/tools/copilot/copilot_add_copilot_seats_for_users.go new file mode 100644 index 0000000..8f3fba7 --- /dev/null +++ b/MCP/tools/copilot/copilot_add_copilot_seats_for_users.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_add_copilot_seats_for_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/copilot/billing/selected_users", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_add_copilot_seats_for_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_copilot_billing_selected_users", + mcp.WithDescription("Add users to the Copilot subscription for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_usernames", mcp.Required(), mcp.Description("Input parameter: The usernames of the organization members to be granted access to GitHub Copilot.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_add_copilot_seats_for_usersHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_teams.go b/MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_teams.go new file mode 100644 index 0000000..95d8051 --- /dev/null +++ b/MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_teams.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_cancel_copilot_seat_assignment_for_teamsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/copilot/billing/selected_teams", cfg.BaseURL, org) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_cancel_copilot_seat_assignment_for_teamsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_copilot_billing_selected_teams", + mcp.WithDescription("Remove teams from the Copilot subscription for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_teams", mcp.Required(), mcp.Description("Input parameter: The names of teams from which to revoke access to GitHub Copilot.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_cancel_copilot_seat_assignment_for_teamsHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_users.go b/MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_users.go new file mode 100644 index 0000000..7f5c560 --- /dev/null +++ b/MCP/tools/copilot/copilot_cancel_copilot_seat_assignment_for_users.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_cancel_copilot_seat_assignment_for_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/copilot/billing/selected_users", cfg.BaseURL, org) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_cancel_copilot_seat_assignment_for_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_copilot_billing_selected_users", + mcp.WithDescription("Remove users from the Copilot subscription for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("selected_usernames", mcp.Required(), mcp.Description("Input parameter: The usernames of the organization members for which to revoke access to GitHub Copilot.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_cancel_copilot_seat_assignment_for_usersHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_copilot_metrics_for_organization.go b/MCP/tools/copilot/copilot_copilot_metrics_for_organization.go new file mode 100644 index 0000000..0ded174 --- /dev/null +++ b/MCP/tools/copilot/copilot_copilot_metrics_for_organization.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_copilot_metrics_for_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["until"]; ok { + queryParams = append(queryParams, fmt.Sprintf("until=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/copilot/metrics%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_copilot_metrics_for_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_copilot_metrics", + mcp.WithDescription("Get Copilot metrics for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("since", mcp.Description("Show usage metrics since this date. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format (`YYYY-MM-DDTHH:MM:SSZ`). Maximum value is 28 days ago.")), + mcp.WithString("until", mcp.Description("Show usage metrics until this date. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format (`YYYY-MM-DDTHH:MM:SSZ`) and should not preceed the `since` date if it is passed.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of days of metrics to display per page (max 28). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_copilot_metrics_for_organizationHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_copilot_metrics_for_team.go b/MCP/tools/copilot/copilot_copilot_metrics_for_team.go new file mode 100644 index 0000000..2640c14 --- /dev/null +++ b/MCP/tools/copilot/copilot_copilot_metrics_for_team.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_copilot_metrics_for_teamHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["until"]; ok { + queryParams = append(queryParams, fmt.Sprintf("until=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/team/%s/copilot/metrics%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_copilot_metrics_for_teamTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_team_team_slug_copilot_metrics", + mcp.WithDescription("Get Copilot metrics for a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("since", mcp.Description("Show usage metrics since this date. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format (`YYYY-MM-DDTHH:MM:SSZ`). Maximum value is 28 days ago.")), + mcp.WithString("until", mcp.Description("Show usage metrics until this date. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format (`YYYY-MM-DDTHH:MM:SSZ`) and should not preceed the `since` date if it is passed.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of days of metrics to display per page (max 28). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_copilot_metrics_for_teamHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_get_copilot_organization_details.go b/MCP/tools/copilot/copilot_get_copilot_organization_details.go new file mode 100644 index 0000000..05c4b7a --- /dev/null +++ b/MCP/tools/copilot/copilot_get_copilot_organization_details.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_get_copilot_organization_detailsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/copilot/billing", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_get_copilot_organization_detailsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_copilot_billing", + mcp.WithDescription("Get Copilot seat information and settings for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_get_copilot_organization_detailsHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_get_copilot_seat_details_for_user.go b/MCP/tools/copilot/copilot_get_copilot_seat_details_for_user.go new file mode 100644 index 0000000..ae75b54 --- /dev/null +++ b/MCP/tools/copilot/copilot_get_copilot_seat_details_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_get_copilot_seat_details_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/members/%s/copilot", cfg.BaseURL, org, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_get_copilot_seat_details_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_members_username_copilot", + mcp.WithDescription("Get Copilot seat assignment details for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_get_copilot_seat_details_for_userHandler(cfg), + } +} diff --git a/MCP/tools/copilot/copilot_list_copilot_seats.go b/MCP/tools/copilot/copilot_list_copilot_seats.go new file mode 100644 index 0000000..9413a2d --- /dev/null +++ b/MCP/tools/copilot/copilot_list_copilot_seats.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Copilot_list_copilot_seatsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/copilot/billing/seats%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCopilot_list_copilot_seatsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_copilot_billing_seats", + mcp.WithDescription("List all Copilot seat assignments for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Copilot_list_copilot_seatsHandler(cfg), + } +} diff --git a/MCP/tools/credentials/credentials_revoke.go b/MCP/tools/credentials/credentials_revoke.go new file mode 100644 index 0000000..3f7cba8 --- /dev/null +++ b/MCP/tools/credentials/credentials_revoke.go @@ -0,0 +1,87 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Credentials_revokeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/credentials/revoke", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateCredentials_revokeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_credentials_revoke", + mcp.WithDescription("Revoke a list of credentials"), + mcp.WithArray("credentials", mcp.Required(), mcp.Description("Input parameter: A list of credentials to be revoked, up to 1000 per request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Credentials_revokeHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_add_selected_repo_to_org_secret.go b/MCP/tools/dependabot/dependabot_add_selected_repo_to_org_secret.go new file mode 100644 index 0000000..ef1b246 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_add_selected_repo_to_org_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_add_selected_repo_to_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s/repositories/%s", cfg.BaseURL, org, secret_name, repository_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_add_selected_repo_to_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_dependabot_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Add selected repository to an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_add_selected_repo_to_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_create_or_update_org_secret.go b/MCP/tools/dependabot/dependabot_create_or_update_org_secret.go new file mode 100644 index 0000000..55d6be0 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_create_or_update_org_secret.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_create_or_update_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_create_or_update_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_dependabot_secrets_secret_name", + mcp.WithDescription("Create or update an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository ids that can access the organization secret. You can only provide a list of repository ids when the `visibility` is set to `selected`. You can manage the list of selected repositories using the [List selected repositories for an organization secret](https://docs.github.com/rest/dependabot/secrets#list-selected-repositories-for-an-organization-secret), [Set selected repositories for an organization secret](https://docs.github.com/rest/dependabot/secrets#set-selected-repositories-for-an-organization-secret), and [Remove selected repository from an organization secret](https://docs.github.com/rest/dependabot/secrets#remove-selected-repository-from-an-organization-secret) endpoints.")), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: Which type of organization repositories have access to the organization secret. `selected` means only the repositories specified by `selected_repository_ids` can access the secret.")), + mcp.WithString("encrypted_value", mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get an organization public key](https://docs.github.com/rest/dependabot/secrets#get-an-organization-public-key) endpoint.")), + mcp.WithString("key_id", mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_create_or_update_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_create_or_update_repo_secret.go b/MCP/tools/dependabot/dependabot_create_or_update_repo_secret.go new file mode 100644 index 0000000..727e3a0 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_create_or_update_repo_secret.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_create_or_update_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_create_or_update_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_dependabot_secrets_secret_name", + mcp.WithDescription("Create or update a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("key_id", mcp.Description("Input parameter: ID of the key you used to encrypt the secret.")), + mcp.WithString("encrypted_value", mcp.Description("Input parameter: Value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get a repository public key](https://docs.github.com/rest/dependabot/secrets#get-a-repository-public-key) endpoint.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_create_or_update_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_delete_org_secret.go b/MCP/tools/dependabot/dependabot_delete_org_secret.go new file mode 100644 index 0000000..e613027 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_delete_org_secret.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_delete_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_delete_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_dependabot_secrets_secret_name", + mcp.WithDescription("Delete an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_delete_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_delete_repo_secret.go b/MCP/tools/dependabot/dependabot_delete_repo_secret.go new file mode 100644 index 0000000..0ed1f1c --- /dev/null +++ b/MCP/tools/dependabot/dependabot_delete_repo_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_delete_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_delete_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_dependabot_secrets_secret_name", + mcp.WithDescription("Delete a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_delete_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_get_alert.go b/MCP/tools/dependabot/dependabot_get_alert.go new file mode 100644 index 0000000..0f8deb2 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_get_alert.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_get_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/alerts/%s", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_get_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependabot_alerts_alert_number", + mcp.WithDescription("Get a Dependabot alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies a Dependabot alert in its repository.\nYou can find this at the end of the URL for a Dependabot alert within GitHub,\nor in `number` fields in the response from the\n`GET /repos/{owner}/{repo}/dependabot/alerts` operation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_get_alertHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_get_org_public_key.go b/MCP/tools/dependabot/dependabot_get_org_public_key.go new file mode 100644 index 0000000..e312727 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_get_org_public_key.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_get_org_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/public-key", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_get_org_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_dependabot_secrets_public-key", + mcp.WithDescription("Get an organization public key"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_get_org_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_get_org_secret.go b/MCP/tools/dependabot/dependabot_get_org_secret.go new file mode 100644 index 0000000..10238b1 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_get_org_secret.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_get_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_get_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_dependabot_secrets_secret_name", + mcp.WithDescription("Get an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_get_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_get_repo_public_key.go b/MCP/tools/dependabot/dependabot_get_repo_public_key.go new file mode 100644 index 0000000..05b3d4f --- /dev/null +++ b/MCP/tools/dependabot/dependabot_get_repo_public_key.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_get_repo_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/secrets/public-key", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_get_repo_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependabot_secrets_public-key", + mcp.WithDescription("Get a repository public key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_get_repo_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_get_repo_secret.go b/MCP/tools/dependabot/dependabot_get_repo_secret.go new file mode 100644 index 0000000..e5255cd --- /dev/null +++ b/MCP/tools/dependabot/dependabot_get_repo_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_get_repo_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/secrets/%s", cfg.BaseURL, owner, repo, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_get_repo_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependabot_secrets_secret_name", + mcp.WithDescription("Get a repository secret"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_get_repo_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_list_alerts_for_enterprise.go b/MCP/tools/dependabot/dependabot_list_alerts_for_enterprise.go new file mode 100644 index 0000000..7ef2083 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_list_alerts_for_enterprise.go @@ -0,0 +1,139 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_list_alerts_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["severity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("severity=%v", val)) + } + if val, ok := args["ecosystem"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ecosystem=%v", val)) + } + if val, ok := args["package"]; ok { + queryParams = append(queryParams, fmt.Sprintf("package=%v", val)) + } + if val, ok := args["epss_percentage"]; ok { + queryParams = append(queryParams, fmt.Sprintf("epss_percentage=%v", val)) + } + if val, ok := args["has"]; ok { + queryParams = append(queryParams, fmt.Sprintf("has=%v", val)) + } + if val, ok := args["scope"]; ok { + queryParams = append(queryParams, fmt.Sprintf("scope=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["first"]; ok { + queryParams = append(queryParams, fmt.Sprintf("first=%v", val)) + } + if val, ok := args["last"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/enterprises/%s/dependabot/alerts%s", cfg.BaseURL, enterprise, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_list_alerts_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_enterprises_enterprise_dependabot_alerts", + mcp.WithDescription("List Dependabot alerts for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithString("state", mcp.Description("A comma-separated list of states. If specified, only alerts with these states will be returned.\n\nCan be: `auto_dismissed`, `dismissed`, `fixed`, `open`")), + mcp.WithString("severity", mcp.Description("A comma-separated list of severities. If specified, only alerts with these severities will be returned.\n\nCan be: `low`, `medium`, `high`, `critical`")), + mcp.WithString("ecosystem", mcp.Description("A comma-separated list of ecosystems. If specified, only alerts for these ecosystems will be returned.\n\nCan be: `composer`, `go`, `maven`, `npm`, `nuget`, `pip`, `pub`, `rubygems`, `rust`")), + mcp.WithString("package", mcp.Description("A comma-separated list of package names. If specified, only alerts for these packages will be returned.")), + mcp.WithString("epss_percentage", mcp.Description("CVE Exploit Prediction Scoring System (EPSS) percentage. Can be specified as:\n- An exact number (`n`)\n- Comparators such as `>n`, `=n`, `<=n`\n- A range like `n..n`, where `n` is a number from 0.0 to 1.0\n\nFilters the list of alerts based on EPSS percentages. If specified, only alerts with the provided EPSS percentages will be returned.")), + mcp.WithString("has", mcp.Description("Filters the list of alerts based on whether the alert has the given value. If specified, only alerts meeting this criterion will be returned.\nMultiple `has` filters can be passed to filter for alerts that have all of the values. Currently, only `patch` is supported.")), + mcp.WithString("scope", mcp.Description("The scope of the vulnerable dependency. If specified, only alerts with this scope will be returned.")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.\n`created` means when the alert was created.\n`updated` means when the alert's state last changed.\n`epss_percentage` sorts alerts by the Exploit Prediction Scoring System (EPSS) percentage.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("first", mcp.Description("**Deprecated**. The number of results per page (max 100), starting from the first matching result.\nThis parameter must not be used in combination with `last`.\nInstead, use `per_page` in combination with `after` to fetch the first page of results.")), + mcp.WithNumber("last", mcp.Description("**Deprecated**. The number of results per page (max 100), starting from the last matching result.\nThis parameter must not be used in combination with `first`.\nInstead, use `per_page` in combination with `before` to fetch the last page of results.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_list_alerts_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_list_alerts_for_org.go b/MCP/tools/dependabot/dependabot_list_alerts_for_org.go new file mode 100644 index 0000000..f68c011 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_list_alerts_for_org.go @@ -0,0 +1,139 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_list_alerts_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["severity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("severity=%v", val)) + } + if val, ok := args["ecosystem"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ecosystem=%v", val)) + } + if val, ok := args["package"]; ok { + queryParams = append(queryParams, fmt.Sprintf("package=%v", val)) + } + if val, ok := args["epss_percentage"]; ok { + queryParams = append(queryParams, fmt.Sprintf("epss_percentage=%v", val)) + } + if val, ok := args["has"]; ok { + queryParams = append(queryParams, fmt.Sprintf("has=%v", val)) + } + if val, ok := args["scope"]; ok { + queryParams = append(queryParams, fmt.Sprintf("scope=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["first"]; ok { + queryParams = append(queryParams, fmt.Sprintf("first=%v", val)) + } + if val, ok := args["last"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/alerts%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_list_alerts_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_dependabot_alerts", + mcp.WithDescription("List Dependabot alerts for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("A comma-separated list of states. If specified, only alerts with these states will be returned.\n\nCan be: `auto_dismissed`, `dismissed`, `fixed`, `open`")), + mcp.WithString("severity", mcp.Description("A comma-separated list of severities. If specified, only alerts with these severities will be returned.\n\nCan be: `low`, `medium`, `high`, `critical`")), + mcp.WithString("ecosystem", mcp.Description("A comma-separated list of ecosystems. If specified, only alerts for these ecosystems will be returned.\n\nCan be: `composer`, `go`, `maven`, `npm`, `nuget`, `pip`, `pub`, `rubygems`, `rust`")), + mcp.WithString("package", mcp.Description("A comma-separated list of package names. If specified, only alerts for these packages will be returned.")), + mcp.WithString("epss_percentage", mcp.Description("CVE Exploit Prediction Scoring System (EPSS) percentage. Can be specified as:\n- An exact number (`n`)\n- Comparators such as `>n`, `=n`, `<=n`\n- A range like `n..n`, where `n` is a number from 0.0 to 1.0\n\nFilters the list of alerts based on EPSS percentages. If specified, only alerts with the provided EPSS percentages will be returned.")), + mcp.WithString("has", mcp.Description("Filters the list of alerts based on whether the alert has the given value. If specified, only alerts meeting this criterion will be returned.\nMultiple `has` filters can be passed to filter for alerts that have all of the values. Currently, only `patch` is supported.")), + mcp.WithString("scope", mcp.Description("The scope of the vulnerable dependency. If specified, only alerts with this scope will be returned.")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.\n`created` means when the alert was created.\n`updated` means when the alert's state last changed.\n`epss_percentage` sorts alerts by the Exploit Prediction Scoring System (EPSS) percentage.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("first", mcp.Description("**Deprecated**. The number of results per page (max 100), starting from the first matching result.\nThis parameter must not be used in combination with `last`.\nInstead, use `per_page` in combination with `after` to fetch the first page of results.")), + mcp.WithNumber("last", mcp.Description("**Deprecated**. The number of results per page (max 100), starting from the last matching result.\nThis parameter must not be used in combination with `first`.\nInstead, use `per_page` in combination with `before` to fetch the last page of results.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_list_alerts_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_list_alerts_for_repo.go b/MCP/tools/dependabot/dependabot_list_alerts_for_repo.go new file mode 100644 index 0000000..0a53c4b --- /dev/null +++ b/MCP/tools/dependabot/dependabot_list_alerts_for_repo.go @@ -0,0 +1,156 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_list_alerts_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["severity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("severity=%v", val)) + } + if val, ok := args["ecosystem"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ecosystem=%v", val)) + } + if val, ok := args["package"]; ok { + queryParams = append(queryParams, fmt.Sprintf("package=%v", val)) + } + if val, ok := args["manifest"]; ok { + queryParams = append(queryParams, fmt.Sprintf("manifest=%v", val)) + } + if val, ok := args["epss_percentage"]; ok { + queryParams = append(queryParams, fmt.Sprintf("epss_percentage=%v", val)) + } + if val, ok := args["has"]; ok { + queryParams = append(queryParams, fmt.Sprintf("has=%v", val)) + } + if val, ok := args["scope"]; ok { + queryParams = append(queryParams, fmt.Sprintf("scope=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["first"]; ok { + queryParams = append(queryParams, fmt.Sprintf("first=%v", val)) + } + if val, ok := args["last"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/alerts%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_list_alerts_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependabot_alerts", + mcp.WithDescription("List Dependabot alerts for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("A comma-separated list of states. If specified, only alerts with these states will be returned.\n\nCan be: `auto_dismissed`, `dismissed`, `fixed`, `open`")), + mcp.WithString("severity", mcp.Description("A comma-separated list of severities. If specified, only alerts with these severities will be returned.\n\nCan be: `low`, `medium`, `high`, `critical`")), + mcp.WithString("ecosystem", mcp.Description("A comma-separated list of ecosystems. If specified, only alerts for these ecosystems will be returned.\n\nCan be: `composer`, `go`, `maven`, `npm`, `nuget`, `pip`, `pub`, `rubygems`, `rust`")), + mcp.WithString("package", mcp.Description("A comma-separated list of package names. If specified, only alerts for these packages will be returned.")), + mcp.WithString("manifest", mcp.Description("A comma-separated list of full manifest paths. If specified, only alerts for these manifests will be returned.")), + mcp.WithString("epss_percentage", mcp.Description("CVE Exploit Prediction Scoring System (EPSS) percentage. Can be specified as:\n- An exact number (`n`)\n- Comparators such as `>n`, `=n`, `<=n`\n- A range like `n..n`, where `n` is a number from 0.0 to 1.0\n\nFilters the list of alerts based on EPSS percentages. If specified, only alerts with the provided EPSS percentages will be returned.")), + mcp.WithString("has", mcp.Description("Filters the list of alerts based on whether the alert has the given value. If specified, only alerts meeting this criterion will be returned.\nMultiple `has` filters can be passed to filter for alerts that have all of the values. Currently, only `patch` is supported.")), + mcp.WithString("scope", mcp.Description("The scope of the vulnerable dependency. If specified, only alerts with this scope will be returned.")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.\n`created` means when the alert was created.\n`updated` means when the alert's state last changed.\n`epss_percentage` sorts alerts by the Exploit Prediction Scoring System (EPSS) percentage.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("page", mcp.Description("**Closing down notice**. Page number of the results to fetch. Use cursor-based pagination with `before` or `after` instead.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("first", mcp.Description("**Deprecated**. The number of results per page (max 100), starting from the first matching result.\nThis parameter must not be used in combination with `last`.\nInstead, use `per_page` in combination with `after` to fetch the first page of results.")), + mcp.WithNumber("last", mcp.Description("**Deprecated**. The number of results per page (max 100), starting from the last matching result.\nThis parameter must not be used in combination with `first`.\nInstead, use `per_page` in combination with `before` to fetch the last page of results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_list_alerts_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_list_org_secrets.go b/MCP/tools/dependabot/dependabot_list_org_secrets.go new file mode 100644 index 0000000..c652d9a --- /dev/null +++ b/MCP/tools/dependabot/dependabot_list_org_secrets.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_list_org_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_list_org_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_dependabot_secrets", + mcp.WithDescription("List organization secrets"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_list_org_secretsHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_list_repo_secrets.go b/MCP/tools/dependabot/dependabot_list_repo_secrets.go new file mode 100644 index 0000000..31335c3 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_list_repo_secrets.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_list_repo_secretsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/secrets%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_list_repo_secretsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependabot_secrets", + mcp.WithDescription("List repository secrets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_list_repo_secretsHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_list_selected_repos_for_org_secret.go b/MCP/tools/dependabot/dependabot_list_selected_repos_for_org_secret.go new file mode 100644 index 0000000..d82bfa5 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_list_selected_repos_for_org_secret.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_list_selected_repos_for_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s/repositories%s", cfg.BaseURL, org, secret_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_list_selected_repos_for_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_dependabot_secrets_secret_name_repositories", + mcp.WithDescription("List selected repositories for an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_list_selected_repos_for_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_remove_selected_repo_from_org_secret.go b/MCP/tools/dependabot/dependabot_remove_selected_repo_from_org_secret.go new file mode 100644 index 0000000..360b4f1 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_remove_selected_repo_from_org_secret.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_remove_selected_repo_from_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + repository_idVal, ok := args["repository_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repository_id"), nil + } + repository_id, ok := repository_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repository_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s/repositories/%s", cfg.BaseURL, org, secret_name, repository_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_remove_selected_repo_from_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_dependabot_secrets_secret_name_repositories_repository_id", + mcp.WithDescription("Remove selected repository from an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_remove_selected_repo_from_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_repository_access_for_org.go b/MCP/tools/dependabot/dependabot_repository_access_for_org.go new file mode 100644 index 0000000..db3113b --- /dev/null +++ b/MCP/tools/dependabot/dependabot_repository_access_for_org.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_repository_access_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/organizations/%s/dependabot/repository-access%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_repository_access_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_organizations_org_dependabot_repository-access", + mcp.WithDescription("Lists the repositories Dependabot can access in an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of results to fetch.")), + mcp.WithNumber("per_page", mcp.Description("Number of results per page.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_repository_access_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_set_repository_access_default_level.go b/MCP/tools/dependabot/dependabot_set_repository_access_default_level.go new file mode 100644 index 0000000..98f08bd --- /dev/null +++ b/MCP/tools/dependabot/dependabot_set_repository_access_default_level.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_set_repository_access_default_levelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/organizations/%s/dependabot/repository-access/default-level", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_set_repository_access_default_levelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_organizations_org_dependabot_repository-access_default-level", + mcp.WithDescription("Set the default repository access level for Dependabot"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("default_level", mcp.Required(), mcp.Description("Input parameter: The default repository access level for Dependabot updates.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_set_repository_access_default_levelHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_set_selected_repos_for_org_secret.go b/MCP/tools/dependabot/dependabot_set_selected_repos_for_org_secret.go new file mode 100644 index 0000000..93d1a01 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_set_selected_repos_for_org_secret.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_set_selected_repos_for_org_secretHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/dependabot/secrets/%s/repositories", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_set_selected_repos_for_org_secretTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_dependabot_secrets_secret_name_repositories", + mcp.WithDescription("Set selected repositories for an organization secret"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithArray("selected_repository_ids", mcp.Required(), mcp.Description("Input parameter: An array of repository ids that can access the organization secret. You can only provide a list of repository ids when the `visibility` is set to `selected`. You can add and remove individual repositories using the [Set selected repositories for an organization secret](https://docs.github.com/rest/dependabot/secrets#set-selected-repositories-for-an-organization-secret) and [Remove selected repository from an organization secret](https://docs.github.com/rest/dependabot/secrets#remove-selected-repository-from-an-organization-secret) endpoints.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_set_selected_repos_for_org_secretHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_update_alert.go b/MCP/tools/dependabot/dependabot_update_alert.go new file mode 100644 index 0000000..ff6d220 --- /dev/null +++ b/MCP/tools/dependabot/dependabot_update_alert.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_update_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependabot/alerts/%s", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_update_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_dependabot_alerts_alert_number", + mcp.WithDescription("Update a Dependabot alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies a Dependabot alert in its repository.\nYou can find this at the end of the URL for a Dependabot alert within GitHub,\nor in `number` fields in the response from the\n`GET /repos/{owner}/{repo}/dependabot/alerts` operation.")), + mcp.WithString("dismissed_comment", mcp.Description("Input parameter: An optional comment associated with dismissing the alert.")), + mcp.WithString("dismissed_reason", mcp.Description("Input parameter: **Required when `state` is `dismissed`.** A reason for dismissing the alert.")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: The state of the Dependabot alert.\nA `dismissed_reason` must be provided when setting the state to `dismissed`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_update_alertHandler(cfg), + } +} diff --git a/MCP/tools/dependabot/dependabot_update_repository_access_for_org.go b/MCP/tools/dependabot/dependabot_update_repository_access_for_org.go new file mode 100644 index 0000000..d6f9fdc --- /dev/null +++ b/MCP/tools/dependabot/dependabot_update_repository_access_for_org.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependabot_update_repository_access_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/organizations/%s/dependabot/repository-access", cfg.BaseURL, org) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependabot_update_repository_access_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_organizations_org_dependabot_repository-access", + mcp.WithDescription("Updates Dependabot's repository access list for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("repository_ids_to_add", mcp.Description("Input parameter: List of repository IDs to add.")), + mcp.WithArray("repository_ids_to_remove", mcp.Description("Input parameter: List of repository IDs to remove.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependabot_update_repository_access_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/dependency_graph/dependency_graph_create_repository_snapshot.go b/MCP/tools/dependency_graph/dependency_graph_create_repository_snapshot.go new file mode 100644 index 0000000..ae9aeb9 --- /dev/null +++ b/MCP/tools/dependency_graph/dependency_graph_create_repository_snapshot.go @@ -0,0 +1,112 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependency_graph_create_repository_snapshotHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.Snapshot + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependency-graph/snapshots", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependency_graph_create_repository_snapshotTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_dependency-graph_snapshots", + mcp.WithDescription("Create a snapshot of dependencies for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithObject("job", mcp.Required(), mcp.Description("")), + mcp.WithObject("manifests", mcp.Description("Input parameter: A collection of package manifests, which are a collection of related dependencies declared in a file or representing a logical group of dependencies.")), + mcp.WithObject("metadata", mcp.Description("Input parameter: User-defined metadata to store domain-specific information limited to 8 keys with scalar values.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("Input parameter: The repository branch that triggered this snapshot.")), + mcp.WithString("scanned", mcp.Required(), mcp.Description("Input parameter: The time at which the snapshot was scanned.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The commit SHA associated with this dependency snapshot. Maximum length: 40 characters.")), + mcp.WithNumber("version", mcp.Required(), mcp.Description("Input parameter: The version of the repository snapshot submission.")), + mcp.WithObject("detector", mcp.Required(), mcp.Description("Input parameter: A description of the detector used.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependency_graph_create_repository_snapshotHandler(cfg), + } +} diff --git a/MCP/tools/dependency_graph/dependency_graph_diff_range.go b/MCP/tools/dependency_graph/dependency_graph_diff_range.go new file mode 100644 index 0000000..ef37a11 --- /dev/null +++ b/MCP/tools/dependency_graph/dependency_graph_diff_range.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependency_graph_diff_rangeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + baseheadVal, ok := args["basehead"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: basehead"), nil + } + basehead, ok := baseheadVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: basehead"), nil + } + queryParams := make([]string, 0) + if val, ok := args["name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("name=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/dependency-graph/compare/%s%s", cfg.BaseURL, owner, repo, basehead, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependency_graph_diff_rangeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependency-graph_compare_basehead", + mcp.WithDescription("Get a diff of the dependencies between commits"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("basehead", mcp.Required(), mcp.Description("The base and head Git revisions to compare. The Git revisions will be resolved to commit SHAs. Named revisions will be resolved to their corresponding HEAD commits, and an appropriate merge base will be determined. This parameter expects the format `{base}...{head}`.")), + mcp.WithString("name", mcp.Description("The full path, relative to the repository root, of the dependency manifest file.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependency_graph_diff_rangeHandler(cfg), + } +} diff --git a/MCP/tools/dependency_graph/dependency_graph_export_sbom.go b/MCP/tools/dependency_graph/dependency_graph_export_sbom.go new file mode 100644 index 0000000..e29492d --- /dev/null +++ b/MCP/tools/dependency_graph/dependency_graph_export_sbom.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Dependency_graph_export_sbomHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dependency-graph/sbom", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateDependency_graph_export_sbomTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_dependency-graph_sbom", + mcp.WithDescription("Export a software bill of materials (SBOM) for a repository."), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Dependency_graph_export_sbomHandler(cfg), + } +} diff --git a/MCP/tools/emojis/emojis_get.go b/MCP/tools/emojis/emojis_get.go new file mode 100644 index 0000000..bb1ea37 --- /dev/null +++ b/MCP/tools/emojis/emojis_get.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Emojis_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/emojis", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateEmojis_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_emojis", + mcp.WithDescription("Get emojis"), + ) + + return models.Tool{ + Definition: tool, + Handler: Emojis_getHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_check_is_starred.go b/MCP/tools/gists/gists_check_is_starred.go new file mode 100644 index 0000000..404acf4 --- /dev/null +++ b/MCP/tools/gists/gists_check_is_starred.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_check_is_starredHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + url := fmt.Sprintf("%s/gists/%s/star", cfg.BaseURL, gist_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_check_is_starredTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id_star", + mcp.WithDescription("Check if a gist is starred"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_check_is_starredHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_create.go b/MCP/tools/gists/gists_create.go new file mode 100644 index 0000000..24f2194 --- /dev/null +++ b/MCP/tools/gists/gists_create.go @@ -0,0 +1,89 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_createHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/gists", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_createTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_gists", + mcp.WithDescription("Create a gist"), + mcp.WithString("description", mcp.Description("Input parameter: Description of the gist")), + mcp.WithObject("files", mcp.Required(), mcp.Description("Input parameter: Names and content for the files that make up the gist")), + mcp.WithString("public", mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_createHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_create_comment.go b/MCP/tools/gists/gists_create_comment.go new file mode 100644 index 0000000..64aa10a --- /dev/null +++ b/MCP/tools/gists/gists_create_comment.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_create_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/gists/%s/comments", cfg.BaseURL, gist_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_create_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_gists_gist_id_comments", + mcp.WithDescription("Create a gist comment"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The comment text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_create_commentHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_delete.go b/MCP/tools/gists/gists_delete.go new file mode 100644 index 0000000..a0b7f44 --- /dev/null +++ b/MCP/tools/gists/gists_delete.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_deleteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + url := fmt.Sprintf("%s/gists/%s", cfg.BaseURL, gist_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_deleteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_gists_gist_id", + mcp.WithDescription("Delete a gist"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_deleteHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_delete_comment.go b/MCP/tools/gists/gists_delete_comment.go new file mode 100644 index 0000000..6044036 --- /dev/null +++ b/MCP/tools/gists/gists_delete_comment.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_delete_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/gists/%s/comments/%s", cfg.BaseURL, gist_id, comment_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_delete_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_gists_gist_id_comments_comment_id", + mcp.WithDescription("Delete a gist comment"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_delete_commentHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_fork.go b/MCP/tools/gists/gists_fork.go new file mode 100644 index 0000000..2dd76ab --- /dev/null +++ b/MCP/tools/gists/gists_fork.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_forkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + url := fmt.Sprintf("%s/gists/%s/forks", cfg.BaseURL, gist_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_forkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_gists_gist_id_forks", + mcp.WithDescription("Fork a gist"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_forkHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_get.go b/MCP/tools/gists/gists_get.go new file mode 100644 index 0000000..1fcebbd --- /dev/null +++ b/MCP/tools/gists/gists_get.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + url := fmt.Sprintf("%s/gists/%s", cfg.BaseURL, gist_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id", + mcp.WithDescription("Get a gist"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_getHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_get_comment.go b/MCP/tools/gists/gists_get_comment.go new file mode 100644 index 0000000..65d8fd7 --- /dev/null +++ b/MCP/tools/gists/gists_get_comment.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_get_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/gists/%s/comments/%s", cfg.BaseURL, gist_id, comment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_get_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id_comments_comment_id", + mcp.WithDescription("Get a gist comment"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_get_commentHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_get_revision.go b/MCP/tools/gists/gists_get_revision.go new file mode 100644 index 0000000..02908ec --- /dev/null +++ b/MCP/tools/gists/gists_get_revision.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_get_revisionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + shaVal, ok := args["sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: sha"), nil + } + sha, ok := shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: sha"), nil + } + url := fmt.Sprintf("%s/gists/%s/%s", cfg.BaseURL, gist_id, sha) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_get_revisionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id_sha", + mcp.WithDescription("Get a gist revision"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_get_revisionHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list.go b/MCP/tools/gists/gists_list.go new file mode 100644 index 0000000..afd4210 --- /dev/null +++ b/MCP/tools/gists/gists_list.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/gists%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists", + mcp.WithDescription("List gists for the authenticated user"), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_listHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list_comments.go b/MCP/tools/gists/gists_list_comments.go new file mode 100644 index 0000000..f73d486 --- /dev/null +++ b/MCP/tools/gists/gists_list_comments.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_list_commentsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/gists/%s/comments%s", cfg.BaseURL, gist_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_list_commentsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id_comments", + mcp.WithDescription("List gist comments"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_list_commentsHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list_commits.go b/MCP/tools/gists/gists_list_commits.go new file mode 100644 index 0000000..1b9b61d --- /dev/null +++ b/MCP/tools/gists/gists_list_commits.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_list_commitsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/gists/%s/commits%s", cfg.BaseURL, gist_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_list_commitsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id_commits", + mcp.WithDescription("List gist commits"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_list_commitsHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list_for_user.go b/MCP/tools/gists/gists_list_for_user.go new file mode 100644 index 0000000..f53017d --- /dev/null +++ b/MCP/tools/gists/gists_list_for_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_list_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/gists%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_list_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_gists", + mcp.WithDescription("List gists for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_list_for_userHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list_forks.go b/MCP/tools/gists/gists_list_forks.go new file mode 100644 index 0000000..ac441d0 --- /dev/null +++ b/MCP/tools/gists/gists_list_forks.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_list_forksHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/gists/%s/forks%s", cfg.BaseURL, gist_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_list_forksTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_gist_id_forks", + mcp.WithDescription("List gist forks"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_list_forksHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list_public.go b/MCP/tools/gists/gists_list_public.go new file mode 100644 index 0000000..23ae0a1 --- /dev/null +++ b/MCP/tools/gists/gists_list_public.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_list_publicHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/gists/public%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_list_publicTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_public", + mcp.WithDescription("List public gists"), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_list_publicHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_list_starred.go b/MCP/tools/gists/gists_list_starred.go new file mode 100644 index 0000000..50f765d --- /dev/null +++ b/MCP/tools/gists/gists_list_starred.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_list_starredHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/gists/starred%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_list_starredTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gists_starred", + mcp.WithDescription("List starred gists"), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_list_starredHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_star.go b/MCP/tools/gists/gists_star.go new file mode 100644 index 0000000..6894ff9 --- /dev/null +++ b/MCP/tools/gists/gists_star.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_starHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + url := fmt.Sprintf("%s/gists/%s/star", cfg.BaseURL, gist_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_starTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_gists_gist_id_star", + mcp.WithDescription("Star a gist"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_starHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_unstar.go b/MCP/tools/gists/gists_unstar.go new file mode 100644 index 0000000..f5145e4 --- /dev/null +++ b/MCP/tools/gists/gists_unstar.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_unstarHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + url := fmt.Sprintf("%s/gists/%s/star", cfg.BaseURL, gist_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_unstarTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_gists_gist_id_star", + mcp.WithDescription("Unstar a gist"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_unstarHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_update.go b/MCP/tools/gists/gists_update.go new file mode 100644 index 0000000..b76e6c5 --- /dev/null +++ b/MCP/tools/gists/gists_update.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/gists/%s", cfg.BaseURL, gist_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_gists_gist_id", + mcp.WithDescription("Update a gist"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithString("description", mcp.Description("Input parameter: The description of the gist.")), + mcp.WithObject("files", mcp.Description("Input parameter: The gist files to be updated, renamed, or deleted. Each `key` must match the current filename\n(including extension) of the targeted gist file. For example: `hello.py`.\n\nTo delete a file, set the whole file to null. For example: `hello.py : null`. The file will also be\ndeleted if the specified object does not contain at least one of `content` or `filename`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_updateHandler(cfg), + } +} diff --git a/MCP/tools/gists/gists_update_comment.go b/MCP/tools/gists/gists_update_comment.go new file mode 100644 index 0000000..838359c --- /dev/null +++ b/MCP/tools/gists/gists_update_comment.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gists_update_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gist_idVal, ok := args["gist_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gist_id"), nil + } + gist_id, ok := gist_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gist_id"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/gists/%s/comments/%s", cfg.BaseURL, gist_id, comment_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGists_update_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_gists_gist_id_comments_comment_id", + mcp.WithDescription("Update a gist comment"), + mcp.WithString("gist_id", mcp.Required(), mcp.Description("The unique identifier of the gist.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The comment text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gists_update_commentHandler(cfg), + } +} diff --git a/MCP/tools/git/git_create_blob.go b/MCP/tools/git/git_create_blob.go new file mode 100644 index 0000000..d76f3c2 --- /dev/null +++ b/MCP/tools/git/git_create_blob.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_create_blobHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/blobs", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_create_blobTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_git_blobs", + mcp.WithDescription("Create a blob"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The new blob's content.")), + mcp.WithString("encoding", mcp.Description("Input parameter: The encoding used for `content`. Currently, `\"utf-8\"` and `\"base64\"` are supported.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_create_blobHandler(cfg), + } +} diff --git a/MCP/tools/git/git_create_commit.go b/MCP/tools/git/git_create_commit.go new file mode 100644 index 0000000..2e59ef9 --- /dev/null +++ b/MCP/tools/git/git_create_commit.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_create_commitHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/commits", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_create_commitTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_git_commits", + mcp.WithDescription("Create a commit"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithObject("committer", mcp.Description("Input parameter: Information about the person who is making the commit. By default, `committer` will use the information set in `author`. See the `author` and `committer` object below for details.")), + mcp.WithString("message", mcp.Required(), mcp.Description("Input parameter: The commit message")), + mcp.WithArray("parents", mcp.Description("Input parameter: The full SHAs of the commits that were the parents of this commit. If omitted or empty, the commit will be written as a root commit. For a single parent, an array of one SHA should be provided; for a merge commit, an array of more than one should be provided.")), + mcp.WithString("signature", mcp.Description("Input parameter: The [PGP signature](https://en.wikipedia.org/wiki/Pretty_Good_Privacy) of the commit. GitHub adds the signature to the `gpgsig` header of the created commit. For a commit signature to be verifiable by Git or GitHub, it must be an ASCII-armored detached PGP signature over the string commit as it would be written to the object database. To pass a `signature` parameter, you need to first manually create a valid PGP signature, which can be complicated. You may find it easier to [use the command line](https://git-scm.com/book/id/v2/Git-Tools-Signing-Your-Work) to create signed commits.")), + mcp.WithString("tree", mcp.Required(), mcp.Description("Input parameter: The SHA of the tree object this commit points to")), + mcp.WithObject("author", mcp.Description("Input parameter: Information about the author of the commit. By default, the `author` will be the authenticated user and the current date. See the `author` and `committer` object below for details.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_create_commitHandler(cfg), + } +} diff --git a/MCP/tools/git/git_create_ref.go b/MCP/tools/git/git_create_ref.go new file mode 100644 index 0000000..b97cd27 --- /dev/null +++ b/MCP/tools/git/git_create_ref.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_create_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/refs", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_create_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_git_refs", + mcp.WithDescription("Create a reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The SHA1 value for this reference.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("Input parameter: The name of the fully qualified reference (ie: `refs/heads/master`). If it doesn't start with 'refs' and have at least two slashes, it will be rejected.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_create_refHandler(cfg), + } +} diff --git a/MCP/tools/git/git_create_tag.go b/MCP/tools/git/git_create_tag.go new file mode 100644 index 0000000..50fae9b --- /dev/null +++ b/MCP/tools/git/git_create_tag.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_create_tagHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/tags", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_create_tagTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_git_tags", + mcp.WithDescription("Create a tag object"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("object", mcp.Required(), mcp.Description("Input parameter: The SHA of the git object this is tagging.")), + mcp.WithString("tag", mcp.Required(), mcp.Description("Input parameter: The tag's name. This is typically a version (e.g., \"v0.0.1\").")), + mcp.WithObject("tagger", mcp.Description("Input parameter: An object with information about the individual creating the tag.")), + mcp.WithString("type", mcp.Required(), mcp.Description("Input parameter: The type of the object we're tagging. Normally this is a `commit` but it can also be a `tree` or a `blob`.")), + mcp.WithString("message", mcp.Required(), mcp.Description("Input parameter: The tag message.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_create_tagHandler(cfg), + } +} diff --git a/MCP/tools/git/git_create_tree.go b/MCP/tools/git/git_create_tree.go new file mode 100644 index 0000000..e913fd8 --- /dev/null +++ b/MCP/tools/git/git_create_tree.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_create_treeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/trees", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_create_treeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_git_trees", + mcp.WithDescription("Create a tree"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("tree", mcp.Required(), mcp.Description("Input parameter: Objects (of `path`, `mode`, `type`, and `sha`) specifying a tree structure.")), + mcp.WithString("base_tree", mcp.Description("Input parameter: The SHA1 of an existing Git tree object which will be used as the base for the new tree. If provided, a new Git tree object will be created from entries in the Git tree object pointed to by `base_tree` and entries defined in the `tree` parameter. Entries defined in the `tree` parameter will overwrite items from `base_tree` with the same `path`. If you're creating new changes on a branch, then normally you'd set `base_tree` to the SHA1 of the Git tree object of the current latest commit on the branch you're working on.\nIf not provided, GitHub will create a new Git tree object from only the entries defined in the `tree` parameter. If you create a new commit pointing to such a tree, then all files which were a part of the parent commit's tree and were not defined in the `tree` parameter will be listed as deleted by the new commit.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_create_treeHandler(cfg), + } +} diff --git a/MCP/tools/git/git_delete_ref.go b/MCP/tools/git/git_delete_ref.go new file mode 100644 index 0000000..d0b31de --- /dev/null +++ b/MCP/tools/git/git_delete_ref.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_delete_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/refs/%s", cfg.BaseURL, owner, repo, ref) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_delete_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_git_refs_ref", + mcp.WithDescription("Delete a reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The Git reference. For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_delete_refHandler(cfg), + } +} diff --git a/MCP/tools/git/git_get_blob.go b/MCP/tools/git/git_get_blob.go new file mode 100644 index 0000000..5ce1bc5 --- /dev/null +++ b/MCP/tools/git/git_get_blob.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_get_blobHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + file_shaVal, ok := args["file_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: file_sha"), nil + } + file_sha, ok := file_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: file_sha"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/blobs/%s", cfg.BaseURL, owner, repo, file_sha) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Blob + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_get_blobTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_git_blobs_file_sha", + mcp.WithDescription("Get a blob"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("file_sha", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_get_blobHandler(cfg), + } +} diff --git a/MCP/tools/git/git_get_commit.go b/MCP/tools/git/git_get_commit.go new file mode 100644 index 0000000..110c366 --- /dev/null +++ b/MCP/tools/git/git_get_commit.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_get_commitHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + commit_shaVal, ok := args["commit_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: commit_sha"), nil + } + commit_sha, ok := commit_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: commit_sha"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/commits/%s", cfg.BaseURL, owner, repo, commit_sha) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_get_commitTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_git_commits_commit_sha", + mcp.WithDescription("Get a commit object"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("commit_sha", mcp.Required(), mcp.Description("The SHA of the commit.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_get_commitHandler(cfg), + } +} diff --git a/MCP/tools/git/git_get_ref.go b/MCP/tools/git/git_get_ref.go new file mode 100644 index 0000000..b6f0cd8 --- /dev/null +++ b/MCP/tools/git/git_get_ref.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_get_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/ref/%s", cfg.BaseURL, owner, repo, ref) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_get_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_git_ref_ref", + mcp.WithDescription("Get a reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The Git reference. For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_get_refHandler(cfg), + } +} diff --git a/MCP/tools/git/git_get_tag.go b/MCP/tools/git/git_get_tag.go new file mode 100644 index 0000000..cbe9da2 --- /dev/null +++ b/MCP/tools/git/git_get_tag.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_get_tagHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + tag_shaVal, ok := args["tag_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: tag_sha"), nil + } + tag_sha, ok := tag_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: tag_sha"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/tags/%s", cfg.BaseURL, owner, repo, tag_sha) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_get_tagTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_git_tags_tag_sha", + mcp.WithDescription("Get a tag"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("tag_sha", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_get_tagHandler(cfg), + } +} diff --git a/MCP/tools/git/git_get_tree.go b/MCP/tools/git/git_get_tree.go new file mode 100644 index 0000000..991110b --- /dev/null +++ b/MCP/tools/git/git_get_tree.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_get_treeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + tree_shaVal, ok := args["tree_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: tree_sha"), nil + } + tree_sha, ok := tree_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: tree_sha"), nil + } + queryParams := make([]string, 0) + if val, ok := args["recursive"]; ok { + queryParams = append(queryParams, fmt.Sprintf("recursive=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/git/trees/%s%s", cfg.BaseURL, owner, repo, tree_sha, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_get_treeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_git_trees_tree_sha", + mcp.WithDescription("Get a tree"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("tree_sha", mcp.Required(), mcp.Description("The SHA1 value or ref (branch or tag) name of the tree.")), + mcp.WithString("recursive", mcp.Description("Setting this parameter to any value returns the objects or subtrees referenced by the tree specified in `:tree_sha`. For example, setting `recursive` to any of the following will enable returning objects or subtrees: `0`, `1`, `\"true\"`, and `\"false\"`. Omit this parameter to prevent recursively returning objects or subtrees.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_get_treeHandler(cfg), + } +} diff --git a/MCP/tools/git/git_list_matching_refs.go b/MCP/tools/git/git_list_matching_refs.go new file mode 100644 index 0000000..a1f6938 --- /dev/null +++ b/MCP/tools/git/git_list_matching_refs.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_list_matching_refsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/matching-refs/%s", cfg.BaseURL, owner, repo, ref) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_list_matching_refsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_git_matching-refs_ref", + mcp.WithDescription("List matching references"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The Git reference. For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_list_matching_refsHandler(cfg), + } +} diff --git a/MCP/tools/git/git_update_ref.go b/MCP/tools/git/git_update_ref.go new file mode 100644 index 0000000..bcd1fc8 --- /dev/null +++ b/MCP/tools/git/git_update_ref.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Git_update_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/git/refs/%s", cfg.BaseURL, owner, repo, ref) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGit_update_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_git_refs_ref", + mcp.WithDescription("Update a reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The Git reference. For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The SHA1 value to set this reference to")), + mcp.WithBoolean("force", mcp.Description("Input parameter: Indicates whether to force the update or to make sure the update is a fast-forward update. Leaving this out or setting it to `false` will make sure you're not overwriting work.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Git_update_refHandler(cfg), + } +} diff --git a/MCP/tools/gitignore/gitignore_get_all_templates.go b/MCP/tools/gitignore/gitignore_get_all_templates.go new file mode 100644 index 0000000..e29d475 --- /dev/null +++ b/MCP/tools/gitignore/gitignore_get_all_templates.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gitignore_get_all_templatesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/gitignore/templates", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGitignore_get_all_templatesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gitignore_templates", + mcp.WithDescription("Get all gitignore templates"), + ) + + return models.Tool{ + Definition: tool, + Handler: Gitignore_get_all_templatesHandler(cfg), + } +} diff --git a/MCP/tools/gitignore/gitignore_get_template.go b/MCP/tools/gitignore/gitignore_get_template.go new file mode 100644 index 0000000..211bad0 --- /dev/null +++ b/MCP/tools/gitignore/gitignore_get_template.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Gitignore_get_templateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/gitignore/templates/%s", cfg.BaseURL, name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateGitignore_get_templateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_gitignore_templates_name", + mcp.WithDescription("Get a gitignore template"), + mcp.WithString("name", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Gitignore_get_templateHandler(cfg), + } +} diff --git a/MCP/tools/hosted_compute/hosted_compute_create_network_configuration_for_org.go b/MCP/tools/hosted_compute/hosted_compute_create_network_configuration_for_org.go new file mode 100644 index 0000000..b4da620 --- /dev/null +++ b/MCP/tools/hosted_compute/hosted_compute_create_network_configuration_for_org.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Hosted_compute_create_network_configuration_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/network-configurations", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateHosted_compute_create_network_configuration_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_settings_network-configurations", + mcp.WithDescription("Create a hosted compute network configuration for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the network configuration. Must be between 1 and 100 characters and may only contain upper and lowercase letters a-z, numbers 0-9, '.', '-', and '_'.")), + mcp.WithArray("network_settings_ids", mcp.Required(), mcp.Description("Input parameter: The identifier of the network settings to use for the network configuration. Exactly one network settings must be specified.")), + mcp.WithString("compute_service", mcp.Description("Input parameter: The hosted compute service to use for the network configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Hosted_compute_create_network_configuration_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/hosted_compute/hosted_compute_delete_network_configuration_from_org.go b/MCP/tools/hosted_compute/hosted_compute_delete_network_configuration_from_org.go new file mode 100644 index 0000000..2c6a67d --- /dev/null +++ b/MCP/tools/hosted_compute/hosted_compute_delete_network_configuration_from_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Hosted_compute_delete_network_configuration_from_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + network_configuration_idVal, ok := args["network_configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: network_configuration_id"), nil + } + network_configuration_id, ok := network_configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: network_configuration_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/network-configurations/%s", cfg.BaseURL, org, network_configuration_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateHosted_compute_delete_network_configuration_from_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_settings_network-configurations_network_configuration_id", + mcp.WithDescription("Delete a hosted compute network configuration from an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("network_configuration_id", mcp.Required(), mcp.Description("Unique identifier of the hosted compute network configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Hosted_compute_delete_network_configuration_from_orgHandler(cfg), + } +} diff --git a/MCP/tools/hosted_compute/hosted_compute_get_network_configuration_for_org.go b/MCP/tools/hosted_compute/hosted_compute_get_network_configuration_for_org.go new file mode 100644 index 0000000..e7d08a3 --- /dev/null +++ b/MCP/tools/hosted_compute/hosted_compute_get_network_configuration_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Hosted_compute_get_network_configuration_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + network_configuration_idVal, ok := args["network_configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: network_configuration_id"), nil + } + network_configuration_id, ok := network_configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: network_configuration_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/network-configurations/%s", cfg.BaseURL, org, network_configuration_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateHosted_compute_get_network_configuration_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_settings_network-configurations_network_configuration_id", + mcp.WithDescription("Get a hosted compute network configuration for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("network_configuration_id", mcp.Required(), mcp.Description("Unique identifier of the hosted compute network configuration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Hosted_compute_get_network_configuration_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/hosted_compute/hosted_compute_get_network_settings_for_org.go b/MCP/tools/hosted_compute/hosted_compute_get_network_settings_for_org.go new file mode 100644 index 0000000..9f38b83 --- /dev/null +++ b/MCP/tools/hosted_compute/hosted_compute_get_network_settings_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Hosted_compute_get_network_settings_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + network_settings_idVal, ok := args["network_settings_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: network_settings_id"), nil + } + network_settings_id, ok := network_settings_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: network_settings_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/network-settings/%s", cfg.BaseURL, org, network_settings_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateHosted_compute_get_network_settings_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_settings_network-settings_network_settings_id", + mcp.WithDescription("Get a hosted compute network settings resource for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("network_settings_id", mcp.Required(), mcp.Description("Unique identifier of the hosted compute network settings.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Hosted_compute_get_network_settings_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/hosted_compute/hosted_compute_list_network_configurations_for_org.go b/MCP/tools/hosted_compute/hosted_compute_list_network_configurations_for_org.go new file mode 100644 index 0000000..167f235 --- /dev/null +++ b/MCP/tools/hosted_compute/hosted_compute_list_network_configurations_for_org.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Hosted_compute_list_network_configurations_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/settings/network-configurations%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateHosted_compute_list_network_configurations_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_settings_network-configurations", + mcp.WithDescription("List hosted compute network configurations for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Hosted_compute_list_network_configurations_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/hosted_compute/hosted_compute_update_network_configuration_for_org.go b/MCP/tools/hosted_compute/hosted_compute_update_network_configuration_for_org.go new file mode 100644 index 0000000..9e8db1c --- /dev/null +++ b/MCP/tools/hosted_compute/hosted_compute_update_network_configuration_for_org.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Hosted_compute_update_network_configuration_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + network_configuration_idVal, ok := args["network_configuration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: network_configuration_id"), nil + } + network_configuration_id, ok := network_configuration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: network_configuration_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/settings/network-configurations/%s", cfg.BaseURL, org, network_configuration_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateHosted_compute_update_network_configuration_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_settings_network-configurations_network_configuration_id", + mcp.WithDescription("Update a hosted compute network configuration for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("network_configuration_id", mcp.Required(), mcp.Description("Unique identifier of the hosted compute network configuration.")), + mcp.WithString("compute_service", mcp.Description("Input parameter: The hosted compute service to use for the network configuration.")), + mcp.WithString("name", mcp.Description("Input parameter: Name of the network configuration. Must be between 1 and 100 characters and may only contain upper and lowercase letters a-z, numbers 0-9, '.', '-', and '_'.")), + mcp.WithArray("network_settings_ids", mcp.Description("Input parameter: The identifier of the network settings to use for the network configuration. Exactly one network settings must be specified.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Hosted_compute_update_network_configuration_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_get_restrictions_for_authenticated_user.go b/MCP/tools/interactions/interactions_get_restrictions_for_authenticated_user.go new file mode 100644 index 0000000..1da924b --- /dev/null +++ b/MCP/tools/interactions/interactions_get_restrictions_for_authenticated_user.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_get_restrictions_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/user/interaction-limits", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_get_restrictions_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_interaction-limits", + mcp.WithDescription("Get interaction restrictions for your public repositories"), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_get_restrictions_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_get_restrictions_for_org.go b/MCP/tools/interactions/interactions_get_restrictions_for_org.go new file mode 100644 index 0000000..451047a --- /dev/null +++ b/MCP/tools/interactions/interactions_get_restrictions_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_get_restrictions_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/interaction-limits", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_get_restrictions_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_interaction-limits", + mcp.WithDescription("Get interaction restrictions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_get_restrictions_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_get_restrictions_for_repo.go b/MCP/tools/interactions/interactions_get_restrictions_for_repo.go new file mode 100644 index 0000000..0ed2c60 --- /dev/null +++ b/MCP/tools/interactions/interactions_get_restrictions_for_repo.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_get_restrictions_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/interaction-limits", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_get_restrictions_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_interaction-limits", + mcp.WithDescription("Get interaction restrictions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_get_restrictions_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_remove_restrictions_for_authenticated_user.go b/MCP/tools/interactions/interactions_remove_restrictions_for_authenticated_user.go new file mode 100644 index 0000000..83ac7ff --- /dev/null +++ b/MCP/tools/interactions/interactions_remove_restrictions_for_authenticated_user.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_remove_restrictions_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/user/interaction-limits", cfg.BaseURL) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_remove_restrictions_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_interaction-limits", + mcp.WithDescription("Remove interaction restrictions from your public repositories"), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_remove_restrictions_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_remove_restrictions_for_org.go b/MCP/tools/interactions/interactions_remove_restrictions_for_org.go new file mode 100644 index 0000000..9ce95e4 --- /dev/null +++ b/MCP/tools/interactions/interactions_remove_restrictions_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_remove_restrictions_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/interaction-limits", cfg.BaseURL, org) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_remove_restrictions_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_interaction-limits", + mcp.WithDescription("Remove interaction restrictions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_remove_restrictions_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_remove_restrictions_for_repo.go b/MCP/tools/interactions/interactions_remove_restrictions_for_repo.go new file mode 100644 index 0000000..6c8a40f --- /dev/null +++ b/MCP/tools/interactions/interactions_remove_restrictions_for_repo.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_remove_restrictions_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/interaction-limits", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_remove_restrictions_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_interaction-limits", + mcp.WithDescription("Remove interaction restrictions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_remove_restrictions_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_set_restrictions_for_authenticated_user.go b/MCP/tools/interactions/interactions_set_restrictions_for_authenticated_user.go new file mode 100644 index 0000000..9fa6d15 --- /dev/null +++ b/MCP/tools/interactions/interactions_set_restrictions_for_authenticated_user.go @@ -0,0 +1,88 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_set_restrictions_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/interaction-limits", cfg.BaseURL) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_set_restrictions_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_interaction-limits", + mcp.WithDescription("Set interaction restrictions for your public repositories"), + mcp.WithString("expiry", mcp.Description("Input parameter: The duration of the interaction restriction. Default: `one_day`.")), + mcp.WithString("limit", mcp.Required(), mcp.Description("Input parameter: The type of GitHub user that can comment, open issues, or create pull requests while the interaction limit is in effect.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_set_restrictions_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_set_restrictions_for_org.go b/MCP/tools/interactions/interactions_set_restrictions_for_org.go new file mode 100644 index 0000000..d0af8be --- /dev/null +++ b/MCP/tools/interactions/interactions_set_restrictions_for_org.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_set_restrictions_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/interaction-limits", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_set_restrictions_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_interaction-limits", + mcp.WithDescription("Set interaction restrictions for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("expiry", mcp.Description("Input parameter: The duration of the interaction restriction. Default: `one_day`.")), + mcp.WithString("limit", mcp.Required(), mcp.Description("Input parameter: The type of GitHub user that can comment, open issues, or create pull requests while the interaction limit is in effect.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_set_restrictions_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/interactions/interactions_set_restrictions_for_repo.go b/MCP/tools/interactions/interactions_set_restrictions_for_repo.go new file mode 100644 index 0000000..0140e6e --- /dev/null +++ b/MCP/tools/interactions/interactions_set_restrictions_for_repo.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Interactions_set_restrictions_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/interaction-limits", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateInteractions_set_restrictions_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_interaction-limits", + mcp.WithDescription("Set interaction restrictions for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("expiry", mcp.Description("Input parameter: The duration of the interaction restriction. Default: `one_day`.")), + mcp.WithString("limit", mcp.Required(), mcp.Description("Input parameter: The type of GitHub user that can comment, open issues, or create pull requests while the interaction limit is in effect.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Interactions_set_restrictions_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_add_assignees.go b/MCP/tools/issues/issues_add_assignees.go new file mode 100644 index 0000000..475dac8 --- /dev/null +++ b/MCP/tools/issues/issues_add_assignees.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_add_assigneesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/assignees", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_add_assigneesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues_issue_number_assignees", + mcp.WithDescription("Add assignees to an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithArray("assignees", mcp.Description("Input parameter: Usernames of people to assign this issue to. _NOTE: Only users with push access can add assignees to an issue. Assignees are silently ignored otherwise._")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_add_assigneesHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_add_labels.go b/MCP/tools/issues/issues_add_labels.go new file mode 100644 index 0000000..e042038 --- /dev/null +++ b/MCP/tools/issues/issues_add_labels.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_add_labelsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/labels", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_add_labelsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues_issue_number_labels", + mcp.WithDescription("Add labels to an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_add_labelsHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_add_sub_issue.go b/MCP/tools/issues/issues_add_sub_issue.go new file mode 100644 index 0000000..e112410 --- /dev/null +++ b/MCP/tools/issues/issues_add_sub_issue.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_add_sub_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/sub_issues", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_add_sub_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues_issue_number_sub_issues", + mcp.WithDescription("Add sub-issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithBoolean("replace_parent", mcp.Description("Input parameter: Option that, when true, instructs the operation to replace the sub-issues current parent issue")), + mcp.WithNumber("sub_issue_id", mcp.Required(), mcp.Description("Input parameter: The id of the sub-issue to add. The sub-issue must belong to the same repository owner as the parent issue")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_add_sub_issueHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_check_user_can_be_assigned.go b/MCP/tools/issues/issues_check_user_can_be_assigned.go new file mode 100644 index 0000000..af7f312 --- /dev/null +++ b/MCP/tools/issues/issues_check_user_can_be_assigned.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_check_user_can_be_assignedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + assigneeVal, ok := args["assignee"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: assignee"), nil + } + assignee, ok := assigneeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: assignee"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/assignees/%s", cfg.BaseURL, owner, repo, assignee) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_check_user_can_be_assignedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_assignees_assignee", + mcp.WithDescription("Check if a user can be assigned"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("assignee", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_check_user_can_be_assignedHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_check_user_can_be_assigned_to_issue.go b/MCP/tools/issues/issues_check_user_can_be_assigned_to_issue.go new file mode 100644 index 0000000..9ffbb0a --- /dev/null +++ b/MCP/tools/issues/issues_check_user_can_be_assigned_to_issue.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_check_user_can_be_assigned_to_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + assigneeVal, ok := args["assignee"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: assignee"), nil + } + assignee, ok := assigneeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: assignee"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/assignees/%s", cfg.BaseURL, owner, repo, issue_number, assignee) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_check_user_can_be_assigned_to_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_assignees_assignee", + mcp.WithDescription("Check if a user can be assigned to a issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("assignee", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_check_user_can_be_assigned_to_issueHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_create.go b/MCP/tools/issues/issues_create.go new file mode 100644 index 0000000..3d67518 --- /dev/null +++ b/MCP/tools/issues/issues_create.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_createHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_createTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues", + mcp.WithDescription("Create an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("type", mcp.Description("Input parameter: The name of the issue type to associate with this issue. _NOTE: Only users with push access can set the type for new issues. The type is silently dropped otherwise._")), + mcp.WithString("assignee", mcp.Description("Input parameter: Login for the user that this issue should be assigned to. _NOTE: Only users with push access can set the assignee for new issues. The assignee is silently dropped otherwise. **This field is closing down.**_")), + mcp.WithArray("assignees", mcp.Description("Input parameter: Logins for Users to assign to this issue. _NOTE: Only users with push access can set assignees for new issues. Assignees are silently dropped otherwise._")), + mcp.WithString("body", mcp.Description("Input parameter: The contents of the issue.")), + mcp.WithArray("labels", mcp.Description("Input parameter: Labels to associate with this issue. _NOTE: Only users with push access can set labels for new issues. Labels are silently dropped otherwise._")), + mcp.WithString("milestone", mcp.Description("")), + mcp.WithString("title", mcp.Required(), mcp.Description("Input parameter: The title of the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_createHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_create_comment.go b/MCP/tools/issues/issues_create_comment.go new file mode 100644 index 0000000..6c4e082 --- /dev/null +++ b/MCP/tools/issues/issues_create_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_create_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/comments", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_create_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues_issue_number_comments", + mcp.WithDescription("Create an issue comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The contents of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_create_commentHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_create_label.go b/MCP/tools/issues/issues_create_label.go new file mode 100644 index 0000000..e31f92e --- /dev/null +++ b/MCP/tools/issues/issues_create_label.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_create_labelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/labels", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_create_labelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_labels", + mcp.WithDescription("Create a label"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the label. Must be 100 characters or fewer.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the label. Emoji can be added to label names, using either native emoji or colon-style markup. For example, typing `:strawberry:` will render the emoji ![:strawberry:](https://github.githubassets.com/images/icons/emoji/unicode/1f353.png \":strawberry:\"). For a full list of available emoji and codes, see \"[Emoji cheat sheet](https://github.com/ikatyang/emoji-cheat-sheet).\"")), + mcp.WithString("color", mcp.Description("Input parameter: The [hexadecimal color code](http://www.color-hex.com/) for the label, without the leading `#`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_create_labelHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_create_milestone.go b/MCP/tools/issues/issues_create_milestone.go new file mode 100644 index 0000000..da4a364 --- /dev/null +++ b/MCP/tools/issues/issues_create_milestone.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_create_milestoneHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/milestones", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Milestone + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_create_milestoneTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_milestones", + mcp.WithDescription("Create a milestone"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("description", mcp.Description("Input parameter: A description of the milestone.")), + mcp.WithString("due_on", mcp.Description("Input parameter: The milestone due date. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("state", mcp.Description("Input parameter: The state of the milestone. Either `open` or `closed`.")), + mcp.WithString("title", mcp.Required(), mcp.Description("Input parameter: The title of the milestone.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_create_milestoneHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_delete_comment.go b/MCP/tools/issues/issues_delete_comment.go new file mode 100644 index 0000000..c19c15a --- /dev/null +++ b/MCP/tools/issues/issues_delete_comment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_delete_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_delete_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_comments_comment_id", + mcp.WithDescription("Delete an issue comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_delete_commentHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_delete_label.go b/MCP/tools/issues/issues_delete_label.go new file mode 100644 index 0000000..6218c21 --- /dev/null +++ b/MCP/tools/issues/issues_delete_label.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_delete_labelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/labels/%s", cfg.BaseURL, owner, repo, name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_delete_labelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_labels_name", + mcp.WithDescription("Delete a label"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_delete_labelHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_delete_milestone.go b/MCP/tools/issues/issues_delete_milestone.go new file mode 100644 index 0000000..cd55e2e --- /dev/null +++ b/MCP/tools/issues/issues_delete_milestone.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_delete_milestoneHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + milestone_numberVal, ok := args["milestone_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: milestone_number"), nil + } + milestone_number, ok := milestone_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: milestone_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/milestones/%s", cfg.BaseURL, owner, repo, milestone_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_delete_milestoneTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_milestones_milestone_number", + mcp.WithDescription("Delete a milestone"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("milestone_number", mcp.Required(), mcp.Description("The number that identifies the milestone.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_delete_milestoneHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_get.go b/MCP/tools/issues/issues_get.go new file mode 100644 index 0000000..8937d60 --- /dev/null +++ b/MCP/tools/issues/issues_get.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number", + mcp.WithDescription("Get an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_getHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_get_comment.go b/MCP/tools/issues/issues_get_comment.go new file mode 100644 index 0000000..a7c3143 --- /dev/null +++ b/MCP/tools/issues/issues_get_comment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_get_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_get_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_comments_comment_id", + mcp.WithDescription("Get an issue comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_get_commentHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_get_event.go b/MCP/tools/issues/issues_get_event.go new file mode 100644 index 0000000..dcf7065 --- /dev/null +++ b/MCP/tools/issues/issues_get_event.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_get_eventHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + event_idVal, ok := args["event_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: event_id"), nil + } + event_id, ok := event_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: event_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/events/%s", cfg.BaseURL, owner, repo, event_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_get_eventTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_events_event_id", + mcp.WithDescription("Get an issue event"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("event_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_get_eventHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_get_label.go b/MCP/tools/issues/issues_get_label.go new file mode 100644 index 0000000..d826009 --- /dev/null +++ b/MCP/tools/issues/issues_get_label.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_get_labelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/labels/%s", cfg.BaseURL, owner, repo, name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_get_labelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_labels_name", + mcp.WithDescription("Get a label"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_get_labelHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_get_milestone.go b/MCP/tools/issues/issues_get_milestone.go new file mode 100644 index 0000000..91671cb --- /dev/null +++ b/MCP/tools/issues/issues_get_milestone.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_get_milestoneHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + milestone_numberVal, ok := args["milestone_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: milestone_number"), nil + } + milestone_number, ok := milestone_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: milestone_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/milestones/%s", cfg.BaseURL, owner, repo, milestone_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Milestone + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_get_milestoneTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_milestones_milestone_number", + mcp.WithDescription("Get a milestone"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("milestone_number", mcp.Required(), mcp.Description("The number that identifies the milestone.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_get_milestoneHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list.go b/MCP/tools/issues/issues_list.go new file mode 100644 index 0000000..669049b --- /dev/null +++ b/MCP/tools/issues/issues_list.go @@ -0,0 +1,122 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["labels"]; ok { + queryParams = append(queryParams, fmt.Sprintf("labels=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["collab"]; ok { + queryParams = append(queryParams, fmt.Sprintf("collab=%v", val)) + } + if val, ok := args["orgs"]; ok { + queryParams = append(queryParams, fmt.Sprintf("orgs=%v", val)) + } + if val, ok := args["owned"]; ok { + queryParams = append(queryParams, fmt.Sprintf("owned=%v", val)) + } + if val, ok := args["pulls"]; ok { + queryParams = append(queryParams, fmt.Sprintf("pulls=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/issues%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_issues", + mcp.WithDescription("List issues assigned to the authenticated user"), + mcp.WithString("filter", mcp.Description("Indicates which sorts of issues to return. `assigned` means issues assigned to you. `created` means issues created by you. `mentioned` means issues mentioning you. `subscribed` means issues you're subscribed to updates for. `all` or `repos` means all issues you can see, regardless of participation or creation.")), + mcp.WithString("state", mcp.Description("Indicates the state of the issues to return.")), + mcp.WithString("labels", mcp.Description("A list of comma separated label names. Example: `bug,ui,@high`")), + mcp.WithString("sort", mcp.Description("What to sort results by.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithBoolean("collab", mcp.Description("")), + mcp.WithBoolean("orgs", mcp.Description("")), + mcp.WithBoolean("owned", mcp.Description("")), + mcp.WithBoolean("pulls", mcp.Description("")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_listHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_assignees.go b/MCP/tools/issues/issues_list_assignees.go new file mode 100644 index 0000000..764feee --- /dev/null +++ b/MCP/tools/issues/issues_list_assignees.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_assigneesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/assignees%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_assigneesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_assignees", + mcp.WithDescription("List assignees"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_assigneesHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_comments.go b/MCP/tools/issues/issues_list_comments.go new file mode 100644 index 0000000..1c86b8b --- /dev/null +++ b/MCP/tools/issues/issues_list_comments.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_commentsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/comments%s", cfg.BaseURL, owner, repo, issue_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_commentsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_comments", + mcp.WithDescription("List issue comments"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_commentsHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_comments_for_repo.go b/MCP/tools/issues/issues_list_comments_for_repo.go new file mode 100644 index 0000000..3bb2b59 --- /dev/null +++ b/MCP/tools/issues/issues_list_comments_for_repo.go @@ -0,0 +1,112 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_comments_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_comments_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_comments", + mcp.WithDescription("List issue comments for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("Either `asc` or `desc`. Ignored without the `sort` parameter.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_comments_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_events.go b/MCP/tools/issues/issues_list_events.go new file mode 100644 index 0000000..168d972 --- /dev/null +++ b/MCP/tools/issues/issues_list_events.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_eventsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/events%s", cfg.BaseURL, owner, repo, issue_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_eventsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_events", + mcp.WithDescription("List issue events"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_eventsHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_events_for_repo.go b/MCP/tools/issues/issues_list_events_for_repo.go new file mode 100644 index 0000000..d504233 --- /dev/null +++ b/MCP/tools/issues/issues_list_events_for_repo.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_events_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/events%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_events_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_events", + mcp.WithDescription("List issue events for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_events_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_events_for_timeline.go b/MCP/tools/issues/issues_list_events_for_timeline.go new file mode 100644 index 0000000..2b2804c --- /dev/null +++ b/MCP/tools/issues/issues_list_events_for_timeline.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_events_for_timelineHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/timeline%s", cfg.BaseURL, owner, repo, issue_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_events_for_timelineTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_timeline", + mcp.WithDescription("List timeline events for an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_events_for_timelineHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_for_authenticated_user.go b/MCP/tools/issues/issues_list_for_authenticated_user.go new file mode 100644 index 0000000..4525d98 --- /dev/null +++ b/MCP/tools/issues/issues_list_for_authenticated_user.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["labels"]; ok { + queryParams = append(queryParams, fmt.Sprintf("labels=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/issues%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_issues", + mcp.WithDescription("List user account issues assigned to the authenticated user"), + mcp.WithString("filter", mcp.Description("Indicates which sorts of issues to return. `assigned` means issues assigned to you. `created` means issues created by you. `mentioned` means issues mentioning you. `subscribed` means issues you're subscribed to updates for. `all` or `repos` means all issues you can see, regardless of participation or creation.")), + mcp.WithString("state", mcp.Description("Indicates the state of the issues to return.")), + mcp.WithString("labels", mcp.Description("A list of comma separated label names. Example: `bug,ui,@high`")), + mcp.WithString("sort", mcp.Description("What to sort results by.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_for_org.go b/MCP/tools/issues/issues_list_for_org.go new file mode 100644 index 0000000..1df7bfb --- /dev/null +++ b/MCP/tools/issues/issues_list_for_org.go @@ -0,0 +1,119 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["labels"]; ok { + queryParams = append(queryParams, fmt.Sprintf("labels=%v", val)) + } + if val, ok := args["type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("type=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/issues%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_issues", + mcp.WithDescription("List organization issues assigned to the authenticated user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("filter", mcp.Description("Indicates which sorts of issues to return. `assigned` means issues assigned to you. `created` means issues created by you. `mentioned` means issues mentioning you. `subscribed` means issues you're subscribed to updates for. `all` or `repos` means all issues you can see, regardless of participation or creation.")), + mcp.WithString("state", mcp.Description("Indicates the state of the issues to return.")), + mcp.WithString("labels", mcp.Description("A list of comma separated label names. Example: `bug,ui,@high`")), + mcp.WithString("type", mcp.Description("Can be the name of an issue type.")), + mcp.WithString("sort", mcp.Description("What to sort results by.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_for_repo.go b/MCP/tools/issues/issues_list_for_repo.go new file mode 100644 index 0000000..cda6265 --- /dev/null +++ b/MCP/tools/issues/issues_list_for_repo.go @@ -0,0 +1,140 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["milestone"]; ok { + queryParams = append(queryParams, fmt.Sprintf("milestone=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["assignee"]; ok { + queryParams = append(queryParams, fmt.Sprintf("assignee=%v", val)) + } + if val, ok := args["type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("type=%v", val)) + } + if val, ok := args["creator"]; ok { + queryParams = append(queryParams, fmt.Sprintf("creator=%v", val)) + } + if val, ok := args["mentioned"]; ok { + queryParams = append(queryParams, fmt.Sprintf("mentioned=%v", val)) + } + if val, ok := args["labels"]; ok { + queryParams = append(queryParams, fmt.Sprintf("labels=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues", + mcp.WithDescription("List repository issues"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("milestone", mcp.Description("If an `integer` is passed, it should refer to a milestone by its `number` field. If the string `*` is passed, issues with any milestone are accepted. If the string `none` is passed, issues without milestones are returned.")), + mcp.WithString("state", mcp.Description("Indicates the state of the issues to return.")), + mcp.WithString("assignee", mcp.Description("Can be the name of a user. Pass in `none` for issues with no assigned user, and `*` for issues assigned to any user.")), + mcp.WithString("type", mcp.Description("Can be the name of an issue type. If the string `*` is passed, issues with any type are accepted. If the string `none` is passed, issues without type are returned.")), + mcp.WithString("creator", mcp.Description("The user that created the issue.")), + mcp.WithString("mentioned", mcp.Description("A user that's mentioned in the issue.")), + mcp.WithString("labels", mcp.Description("A list of comma separated label names. Example: `bug,ui,@high`")), + mcp.WithString("sort", mcp.Description("What to sort results by.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_labels_for_milestone.go b/MCP/tools/issues/issues_list_labels_for_milestone.go new file mode 100644 index 0000000..6c43dbc --- /dev/null +++ b/MCP/tools/issues/issues_list_labels_for_milestone.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_labels_for_milestoneHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + milestone_numberVal, ok := args["milestone_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: milestone_number"), nil + } + milestone_number, ok := milestone_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: milestone_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/milestones/%s/labels%s", cfg.BaseURL, owner, repo, milestone_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_labels_for_milestoneTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_milestones_milestone_number_labels", + mcp.WithDescription("List labels for issues in a milestone"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("milestone_number", mcp.Required(), mcp.Description("The number that identifies the milestone.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_labels_for_milestoneHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_labels_for_repo.go b/MCP/tools/issues/issues_list_labels_for_repo.go new file mode 100644 index 0000000..f7ae6e0 --- /dev/null +++ b/MCP/tools/issues/issues_list_labels_for_repo.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_labels_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/labels%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_labels_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_labels", + mcp.WithDescription("List labels for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_labels_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_labels_on_issue.go b/MCP/tools/issues/issues_list_labels_on_issue.go new file mode 100644 index 0000000..42a9910 --- /dev/null +++ b/MCP/tools/issues/issues_list_labels_on_issue.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_labels_on_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/labels%s", cfg.BaseURL, owner, repo, issue_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_labels_on_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_labels", + mcp.WithDescription("List labels for an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_labels_on_issueHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_milestones.go b/MCP/tools/issues/issues_list_milestones.go new file mode 100644 index 0000000..8f470b5 --- /dev/null +++ b/MCP/tools/issues/issues_list_milestones.go @@ -0,0 +1,112 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_milestonesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/milestones%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Milestone + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_milestonesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_milestones", + mcp.WithDescription("List milestones"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("The state of the milestone. Either `open`, `closed`, or `all`.")), + mcp.WithString("sort", mcp.Description("What to sort results by. Either `due_on` or `completeness`.")), + mcp.WithString("direction", mcp.Description("The direction of the sort. Either `asc` or `desc`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_milestonesHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_list_sub_issues.go b/MCP/tools/issues/issues_list_sub_issues.go new file mode 100644 index 0000000..f283b97 --- /dev/null +++ b/MCP/tools/issues/issues_list_sub_issues.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_list_sub_issuesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/sub_issues%s", cfg.BaseURL, owner, repo, issue_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_list_sub_issuesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_sub_issues", + mcp.WithDescription("List sub-issues"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_list_sub_issuesHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_lock.go b/MCP/tools/issues/issues_lock.go new file mode 100644 index 0000000..96d4eda --- /dev/null +++ b/MCP/tools/issues/issues_lock.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_lockHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/lock", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_lockTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_issues_issue_number_lock", + mcp.WithDescription("Lock an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("lock_reason", mcp.Description("Input parameter: The reason for locking the issue or pull request conversation. Lock will fail if you don't use one of these reasons: \n * `off-topic` \n * `too heated` \n * `resolved` \n * `spam`")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_lockHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_remove_all_labels.go b/MCP/tools/issues/issues_remove_all_labels.go new file mode 100644 index 0000000..36731c2 --- /dev/null +++ b/MCP/tools/issues/issues_remove_all_labels.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_remove_all_labelsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/labels", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_remove_all_labelsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_issue_number_labels", + mcp.WithDescription("Remove all labels from an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_remove_all_labelsHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_remove_assignees.go b/MCP/tools/issues/issues_remove_assignees.go new file mode 100644 index 0000000..52ee5cc --- /dev/null +++ b/MCP/tools/issues/issues_remove_assignees.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_remove_assigneesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/assignees", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_remove_assigneesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_issue_number_assignees", + mcp.WithDescription("Remove assignees from an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithArray("assignees", mcp.Description("Input parameter: Usernames of assignees to remove from an issue. _NOTE: Only users with push access can remove assignees from an issue. Assignees are silently ignored otherwise._")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_remove_assigneesHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_remove_label.go b/MCP/tools/issues/issues_remove_label.go new file mode 100644 index 0000000..9b77ba9 --- /dev/null +++ b/MCP/tools/issues/issues_remove_label.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_remove_labelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/labels/%s", cfg.BaseURL, owner, repo, issue_number, name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_remove_labelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_issue_number_labels_name", + mcp.WithDescription("Remove a label from an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("name", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_remove_labelHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_remove_sub_issue.go b/MCP/tools/issues/issues_remove_sub_issue.go new file mode 100644 index 0000000..bb6468e --- /dev/null +++ b/MCP/tools/issues/issues_remove_sub_issue.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_remove_sub_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/sub_issue", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_remove_sub_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_issue_number_sub_issue", + mcp.WithDescription("Remove sub-issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("sub_issue_id", mcp.Required(), mcp.Description("Input parameter: The id of the sub-issue to remove")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_remove_sub_issueHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_reprioritize_sub_issue.go b/MCP/tools/issues/issues_reprioritize_sub_issue.go new file mode 100644 index 0000000..883670c --- /dev/null +++ b/MCP/tools/issues/issues_reprioritize_sub_issue.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_reprioritize_sub_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/sub_issues/priority", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_reprioritize_sub_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_issues_issue_number_sub_issues_priority", + mcp.WithDescription("Reprioritize sub-issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("after_id", mcp.Description("Input parameter: The id of the sub-issue to be prioritized after (either positional argument after OR before should be specified).")), + mcp.WithNumber("before_id", mcp.Description("Input parameter: The id of the sub-issue to be prioritized before (either positional argument after OR before should be specified).")), + mcp.WithNumber("sub_issue_id", mcp.Required(), mcp.Description("Input parameter: The id of the sub-issue to reprioritize")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_reprioritize_sub_issueHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_set_labels.go b/MCP/tools/issues/issues_set_labels.go new file mode 100644 index 0000000..b07f484 --- /dev/null +++ b/MCP/tools/issues/issues_set_labels.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_set_labelsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/labels", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_set_labelsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_issues_issue_number_labels", + mcp.WithDescription("Set labels for an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_set_labelsHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_unlock.go b/MCP/tools/issues/issues_unlock.go new file mode 100644 index 0000000..4c9b738 --- /dev/null +++ b/MCP/tools/issues/issues_unlock.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_unlockHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/lock", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_unlockTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_issue_number_lock", + mcp.WithDescription("Unlock an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_unlockHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_update.go b/MCP/tools/issues/issues_update.go new file mode 100644 index 0000000..f1a2706 --- /dev/null +++ b/MCP/tools/issues/issues_update.go @@ -0,0 +1,122 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Issue + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_issues_issue_number", + mcp.WithDescription("Update an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("assignee", mcp.Description("Input parameter: Username to assign to this issue. **This field is closing down.**")), + mcp.WithString("state_reason", mcp.Description("Input parameter: The reason for the state change. Ignored unless `state` is changed.")), + mcp.WithString("title", mcp.Description("Input parameter: The title of the issue.")), + mcp.WithArray("assignees", mcp.Description("Input parameter: Usernames to assign to this issue. Pass one or more user logins to _replace_ the set of assignees on this issue. Send an empty array (`[]`) to clear all assignees from the issue. Only users with push access can set assignees for new issues. Without push access to the repository, assignee changes are silently dropped.")), + mcp.WithString("body", mcp.Description("Input parameter: The contents of the issue.")), + mcp.WithString("milestone", mcp.Description("")), + mcp.WithString("state", mcp.Description("Input parameter: The open or closed state of the issue.")), + mcp.WithString("type", mcp.Description("Input parameter: The name of the issue type to associate with this issue or use `null` to remove the current issue type. Only users with push access can set the type for issues. Without push access to the repository, type changes are silently dropped.")), + mcp.WithArray("labels", mcp.Description("Input parameter: Labels to associate with this issue. Pass one or more labels to _replace_ the set of labels on this issue. Send an empty array (`[]`) to clear all labels from the issue. Only users with push access can set labels for issues. Without push access to the repository, label changes are silently dropped.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_updateHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_update_comment.go b/MCP/tools/issues/issues_update_comment.go new file mode 100644 index 0000000..d15763e --- /dev/null +++ b/MCP/tools/issues/issues_update_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_update_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_update_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_issues_comments_comment_id", + mcp.WithDescription("Update an issue comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The contents of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_update_commentHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_update_label.go b/MCP/tools/issues/issues_update_label.go new file mode 100644 index 0000000..033012d --- /dev/null +++ b/MCP/tools/issues/issues_update_label.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_update_labelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + nameVal, ok := args["name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: name"), nil + } + name, ok := nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/labels/%s", cfg.BaseURL, owner, repo, name) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Label + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_update_labelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_labels_name", + mcp.WithDescription("Update a label"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("")), + mcp.WithString("new_name", mcp.Description("Input parameter: The new name of the label. Emoji can be added to label names, using either native emoji or colon-style markup. For example, typing `:strawberry:` will render the emoji ![:strawberry:](https://github.githubassets.com/images/icons/emoji/unicode/1f353.png \":strawberry:\"). For a full list of available emoji and codes, see \"[Emoji cheat sheet](https://github.com/ikatyang/emoji-cheat-sheet).\"")), + mcp.WithString("color", mcp.Description("Input parameter: The [hexadecimal color code](http://www.color-hex.com/) for the label, without the leading `#`.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the label. Must be 100 characters or fewer.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_update_labelHandler(cfg), + } +} diff --git a/MCP/tools/issues/issues_update_milestone.go b/MCP/tools/issues/issues_update_milestone.go new file mode 100644 index 0000000..0939cc5 --- /dev/null +++ b/MCP/tools/issues/issues_update_milestone.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Issues_update_milestoneHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + milestone_numberVal, ok := args["milestone_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: milestone_number"), nil + } + milestone_number, ok := milestone_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: milestone_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/milestones/%s", cfg.BaseURL, owner, repo, milestone_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Milestone + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateIssues_update_milestoneTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_milestones_milestone_number", + mcp.WithDescription("Update a milestone"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("milestone_number", mcp.Required(), mcp.Description("The number that identifies the milestone.")), + mcp.WithString("description", mcp.Description("Input parameter: A description of the milestone.")), + mcp.WithString("due_on", mcp.Description("Input parameter: The milestone due date. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("state", mcp.Description("Input parameter: The state of the milestone. Either `open` or `closed`.")), + mcp.WithString("title", mcp.Description("Input parameter: The title of the milestone.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Issues_update_milestoneHandler(cfg), + } +} diff --git a/MCP/tools/licenses/licenses_get.go b/MCP/tools/licenses/licenses_get.go new file mode 100644 index 0000000..81a4023 --- /dev/null +++ b/MCP/tools/licenses/licenses_get.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Licenses_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + licenseVal, ok := args["license"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: license"), nil + } + license, ok := licenseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: license"), nil + } + url := fmt.Sprintf("%s/licenses/%s", cfg.BaseURL, license) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.License + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateLicenses_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_licenses_license", + mcp.WithDescription("Get a license"), + mcp.WithString("license", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Licenses_getHandler(cfg), + } +} diff --git a/MCP/tools/licenses/licenses_get_all_commonly_used.go b/MCP/tools/licenses/licenses_get_all_commonly_used.go new file mode 100644 index 0000000..d2cbd3f --- /dev/null +++ b/MCP/tools/licenses/licenses_get_all_commonly_used.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Licenses_get_all_commonly_usedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["featured"]; ok { + queryParams = append(queryParams, fmt.Sprintf("featured=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/licenses%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateLicenses_get_all_commonly_usedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_licenses", + mcp.WithDescription("Get all commonly used licenses"), + mcp.WithBoolean("featured", mcp.Description("")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Licenses_get_all_commonly_usedHandler(cfg), + } +} diff --git a/MCP/tools/licenses/licenses_get_for_repo.go b/MCP/tools/licenses/licenses_get_for_repo.go new file mode 100644 index 0000000..7deff92 --- /dev/null +++ b/MCP/tools/licenses/licenses_get_for_repo.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Licenses_get_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/license%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateLicenses_get_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_license", + mcp.WithDescription("Get the license for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Description("The Git reference for the results you want to list. The `ref` for a branch can be formatted either as `refs/heads/` or simply ``. To reference a pull request use `refs/pull//merge`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Licenses_get_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/meta/meta_get.go b/MCP/tools/meta/meta_get.go new file mode 100644 index 0000000..6686e1d --- /dev/null +++ b/MCP/tools/meta/meta_get.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Meta_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/meta", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMeta_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_meta", + mcp.WithDescription("Get GitHub meta information"), + ) + + return models.Tool{ + Definition: tool, + Handler: Meta_getHandler(cfg), + } +} diff --git a/MCP/tools/meta/meta_get_all_versions.go b/MCP/tools/meta/meta_get_all_versions.go new file mode 100644 index 0000000..404d15d --- /dev/null +++ b/MCP/tools/meta/meta_get_all_versions.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Meta_get_all_versionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/versions", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMeta_get_all_versionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_versions", + mcp.WithDescription("Get all API versions"), + ) + + return models.Tool{ + Definition: tool, + Handler: Meta_get_all_versionsHandler(cfg), + } +} diff --git a/MCP/tools/meta/meta_get_zen.go b/MCP/tools/meta/meta_get_zen.go new file mode 100644 index 0000000..b628d3a --- /dev/null +++ b/MCP/tools/meta/meta_get_zen.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Meta_get_zenHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/zen", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMeta_get_zenTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_zen", + mcp.WithDescription("Get the Zen of GitHub"), + ) + + return models.Tool{ + Definition: tool, + Handler: Meta_get_zenHandler(cfg), + } +} diff --git a/MCP/tools/meta/meta_root.go b/MCP/tools/meta/meta_root.go new file mode 100644 index 0000000..c324ac9 --- /dev/null +++ b/MCP/tools/meta/meta_root.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Meta_rootHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Root + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMeta_rootTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_", + mcp.WithDescription("GitHub API Root"), + ) + + return models.Tool{ + Definition: tool, + Handler: Meta_rootHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_cancel_import.go b/MCP/tools/migrations/migrations_cancel_import.go new file mode 100644 index 0000000..1730b72 --- /dev/null +++ b/MCP/tools/migrations/migrations_cancel_import.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_cancel_importHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_cancel_importTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_import", + mcp.WithDescription("Cancel an import"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_cancel_importHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_delete_archive_for_authenticated_user.go b/MCP/tools/migrations/migrations_delete_archive_for_authenticated_user.go new file mode 100644 index 0000000..07a4ed2 --- /dev/null +++ b/MCP/tools/migrations/migrations_delete_archive_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_delete_archive_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + url := fmt.Sprintf("%s/user/migrations/%s/archive", cfg.BaseURL, migration_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_delete_archive_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_migrations_migration_id_archive", + mcp.WithDescription("Delete a user migration archive"), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_delete_archive_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_delete_archive_for_org.go b/MCP/tools/migrations/migrations_delete_archive_for_org.go new file mode 100644 index 0000000..493ba1f --- /dev/null +++ b/MCP/tools/migrations/migrations_delete_archive_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_delete_archive_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/migrations/%s/archive", cfg.BaseURL, org, migration_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_delete_archive_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_migrations_migration_id_archive", + mcp.WithDescription("Delete an organization migration archive"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_delete_archive_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_download_archive_for_org.go b/MCP/tools/migrations/migrations_download_archive_for_org.go new file mode 100644 index 0000000..9bc2e68 --- /dev/null +++ b/MCP/tools/migrations/migrations_download_archive_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_download_archive_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/migrations/%s/archive", cfg.BaseURL, org, migration_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_download_archive_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_migrations_migration_id_archive", + mcp.WithDescription("Download an organization migration archive"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_download_archive_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_get_archive_for_authenticated_user.go b/MCP/tools/migrations/migrations_get_archive_for_authenticated_user.go new file mode 100644 index 0000000..39428eb --- /dev/null +++ b/MCP/tools/migrations/migrations_get_archive_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_get_archive_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + url := fmt.Sprintf("%s/user/migrations/%s/archive", cfg.BaseURL, migration_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_get_archive_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_migrations_migration_id_archive", + mcp.WithDescription("Download a user migration archive"), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_get_archive_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_get_commit_authors.go b/MCP/tools/migrations/migrations_get_commit_authors.go new file mode 100644 index 0000000..8290010 --- /dev/null +++ b/MCP/tools/migrations/migrations_get_commit_authors.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_get_commit_authorsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/import/authors%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_get_commit_authorsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_import_authors", + mcp.WithDescription("Get commit authors"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("since", mcp.Description("A user ID. Only return users with an ID greater than this ID.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_get_commit_authorsHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_get_import_status.go b/MCP/tools/migrations/migrations_get_import_status.go new file mode 100644 index 0000000..ccd1612 --- /dev/null +++ b/MCP/tools/migrations/migrations_get_import_status.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_get_import_statusHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Import + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_get_import_statusTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_import", + mcp.WithDescription("Get an import status"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_get_import_statusHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_get_large_files.go b/MCP/tools/migrations/migrations_get_large_files.go new file mode 100644 index 0000000..4972eed --- /dev/null +++ b/MCP/tools/migrations/migrations_get_large_files.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_get_large_filesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import/large_files", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_get_large_filesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_import_large_files", + mcp.WithDescription("Get large files"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_get_large_filesHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_get_status_for_authenticated_user.go b/MCP/tools/migrations/migrations_get_status_for_authenticated_user.go new file mode 100644 index 0000000..5e74338 --- /dev/null +++ b/MCP/tools/migrations/migrations_get_status_for_authenticated_user.go @@ -0,0 +1,87 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_get_status_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["exclude"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/migrations/%s%s", cfg.BaseURL, migration_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Migration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_get_status_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_migrations_migration_id", + mcp.WithDescription("Get a user migration status"), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + mcp.WithArray("exclude", mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_get_status_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_get_status_for_org.go b/MCP/tools/migrations/migrations_get_status_for_org.go new file mode 100644 index 0000000..a254d57 --- /dev/null +++ b/MCP/tools/migrations/migrations_get_status_for_org.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_get_status_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["exclude"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/migrations/%s%s", cfg.BaseURL, org, migration_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Migration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_get_status_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_migrations_migration_id", + mcp.WithDescription("Get an organization migration status"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + mcp.WithArray("exclude", mcp.Description("Exclude attributes from the API response to improve performance")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_get_status_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_list_for_authenticated_user.go b/MCP/tools/migrations/migrations_list_for_authenticated_user.go new file mode 100644 index 0000000..c47cdaa --- /dev/null +++ b/MCP/tools/migrations/migrations_list_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_list_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/migrations%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Migration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_list_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_migrations", + mcp.WithDescription("List user migrations"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_list_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_list_for_org.go b/MCP/tools/migrations/migrations_list_for_org.go new file mode 100644 index 0000000..f8698bd --- /dev/null +++ b/MCP/tools/migrations/migrations_list_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_list_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["exclude"]; ok { + queryParams = append(queryParams, fmt.Sprintf("exclude=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/migrations%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Migration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_list_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_migrations", + mcp.WithDescription("List organization migrations"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithArray("exclude", mcp.Description("Exclude attributes from the API response to improve performance")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_list_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_list_repos_for_authenticated_user.go b/MCP/tools/migrations/migrations_list_repos_for_authenticated_user.go new file mode 100644 index 0000000..957f68a --- /dev/null +++ b/MCP/tools/migrations/migrations_list_repos_for_authenticated_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_list_repos_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/migrations/%s/repositories%s", cfg.BaseURL, migration_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_list_repos_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_migrations_migration_id_repositories", + mcp.WithDescription("List repositories for a user migration"), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_list_repos_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_list_repos_for_org.go b/MCP/tools/migrations/migrations_list_repos_for_org.go new file mode 100644 index 0000000..1cf9658 --- /dev/null +++ b/MCP/tools/migrations/migrations_list_repos_for_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_list_repos_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/migrations/%s/repositories%s", cfg.BaseURL, org, migration_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_list_repos_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_migrations_migration_id_repositories", + mcp.WithDescription("List repositories in an organization migration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_list_repos_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_map_commit_author.go b/MCP/tools/migrations/migrations_map_commit_author.go new file mode 100644 index 0000000..5967f6a --- /dev/null +++ b/MCP/tools/migrations/migrations_map_commit_author.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_map_commit_authorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + author_idVal, ok := args["author_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: author_id"), nil + } + author_id, ok := author_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: author_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import/authors/%s", cfg.BaseURL, owner, repo, author_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_map_commit_authorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_import_authors_author_id", + mcp.WithDescription("Map a commit author"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("author_id", mcp.Required(), mcp.Description("")), + mcp.WithString("email", mcp.Description("Input parameter: The new Git author email.")), + mcp.WithString("name", mcp.Description("Input parameter: The new Git author name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_map_commit_authorHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_set_lfs_preference.go b/MCP/tools/migrations/migrations_set_lfs_preference.go new file mode 100644 index 0000000..72c12d5 --- /dev/null +++ b/MCP/tools/migrations/migrations_set_lfs_preference.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_set_lfs_preferenceHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import/lfs", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Import + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_set_lfs_preferenceTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_import_lfs", + mcp.WithDescription("Update Git LFS preference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("use_lfs", mcp.Required(), mcp.Description("Input parameter: Whether to store large files during the import. `opt_in` means large files will be stored using Git LFS. `opt_out` means large files will be removed during the import.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_set_lfs_preferenceHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_start_for_authenticated_user.go b/MCP/tools/migrations/migrations_start_for_authenticated_user.go new file mode 100644 index 0000000..9b43d45 --- /dev/null +++ b/MCP/tools/migrations/migrations_start_for_authenticated_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_start_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/migrations", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Migration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_start_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_migrations", + mcp.WithDescription("Start a user migration"), + mcp.WithArray("exclude", mcp.Description("Input parameter: Exclude attributes from the API response to improve performance")), + mcp.WithBoolean("exclude_attachments", mcp.Description("Input parameter: Do not include attachments in the migration")), + mcp.WithBoolean("exclude_git_data", mcp.Description("Input parameter: Indicates whether the repository git data should be excluded from the migration.")), + mcp.WithBoolean("exclude_owner_projects", mcp.Description("Input parameter: Indicates whether projects owned by the organization or users should be excluded.")), + mcp.WithBoolean("lock_repositories", mcp.Description("Input parameter: Lock the repositories being migrated at the start of the migration")), + mcp.WithArray("repositories", mcp.Required(), mcp.Description("")), + mcp.WithBoolean("exclude_metadata", mcp.Description("Input parameter: Indicates whether metadata should be excluded and only git source should be included for the migration.")), + mcp.WithBoolean("exclude_releases", mcp.Description("Input parameter: Do not include releases in the migration")), + mcp.WithBoolean("org_metadata_only", mcp.Description("Input parameter: Indicates whether this should only include organization metadata (repositories array should be empty and will ignore other flags).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_start_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_start_for_org.go b/MCP/tools/migrations/migrations_start_for_org.go new file mode 100644 index 0000000..24103eb --- /dev/null +++ b/MCP/tools/migrations/migrations_start_for_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_start_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/migrations", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Migration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_start_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_migrations", + mcp.WithDescription("Start an organization migration"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithBoolean("exclude_git_data", mcp.Description("Input parameter: Indicates whether the repository git data should be excluded from the migration.")), + mcp.WithBoolean("exclude_owner_projects", mcp.Description("Input parameter: Indicates whether projects owned by the organization or users should be excluded. from the migration.")), + mcp.WithBoolean("lock_repositories", mcp.Description("Input parameter: Indicates whether repositories should be locked (to prevent manipulation) while migrating data.")), + mcp.WithArray("repositories", mcp.Required(), mcp.Description("Input parameter: A list of arrays indicating which repositories should be migrated.")), + mcp.WithArray("exclude", mcp.Description("Input parameter: Exclude related items from being returned in the response in order to improve performance of the request.")), + mcp.WithBoolean("org_metadata_only", mcp.Description("Input parameter: Indicates whether this should only include organization metadata (repositories array should be empty and will ignore other flags).")), + mcp.WithBoolean("exclude_attachments", mcp.Description("Input parameter: Indicates whether attachments should be excluded from the migration (to reduce migration archive file size).")), + mcp.WithBoolean("exclude_metadata", mcp.Description("Input parameter: Indicates whether metadata should be excluded and only git source should be included for the migration.")), + mcp.WithBoolean("exclude_releases", mcp.Description("Input parameter: Indicates whether releases should be excluded from the migration (to reduce migration archive file size).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_start_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_start_import.go b/MCP/tools/migrations/migrations_start_import.go new file mode 100644 index 0000000..d669bee --- /dev/null +++ b/MCP/tools/migrations/migrations_start_import.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_start_importHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Import + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_start_importTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_import", + mcp.WithDescription("Start an import"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("tfvc_project", mcp.Description("Input parameter: For a tfvc import, the name of the project that is being imported.")), + mcp.WithString("vcs", mcp.Description("Input parameter: The originating VCS type. Without this parameter, the import job will take additional time to detect the VCS type before beginning the import. This detection step will be reflected in the response.")), + mcp.WithString("vcs_password", mcp.Description("Input parameter: If authentication is required, the password to provide to `vcs_url`.")), + mcp.WithString("vcs_url", mcp.Required(), mcp.Description("Input parameter: The URL of the originating repository.")), + mcp.WithString("vcs_username", mcp.Description("Input parameter: If authentication is required, the username to provide to `vcs_url`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_start_importHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_unlock_repo_for_authenticated_user.go b/MCP/tools/migrations/migrations_unlock_repo_for_authenticated_user.go new file mode 100644 index 0000000..9d59916 --- /dev/null +++ b/MCP/tools/migrations/migrations_unlock_repo_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_unlock_repo_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + repo_nameVal, ok := args["repo_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo_name"), nil + } + repo_name, ok := repo_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo_name"), nil + } + url := fmt.Sprintf("%s/user/migrations/%s/repos/%s/lock", cfg.BaseURL, migration_id, repo_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_unlock_repo_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_migrations_migration_id_repos_repo_name_lock", + mcp.WithDescription("Unlock a user repository"), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + mcp.WithString("repo_name", mcp.Required(), mcp.Description("repo_name parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_unlock_repo_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_unlock_repo_for_org.go b/MCP/tools/migrations/migrations_unlock_repo_for_org.go new file mode 100644 index 0000000..657b79d --- /dev/null +++ b/MCP/tools/migrations/migrations_unlock_repo_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_unlock_repo_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + migration_idVal, ok := args["migration_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: migration_id"), nil + } + migration_id, ok := migration_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: migration_id"), nil + } + repo_nameVal, ok := args["repo_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo_name"), nil + } + repo_name, ok := repo_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/migrations/%s/repos/%s/lock", cfg.BaseURL, org, migration_id, repo_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_unlock_repo_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_migrations_migration_id_repos_repo_name_lock", + mcp.WithDescription("Unlock an organization repository"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("migration_id", mcp.Required(), mcp.Description("The unique identifier of the migration.")), + mcp.WithString("repo_name", mcp.Required(), mcp.Description("repo_name parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_unlock_repo_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/migrations/migrations_update_import.go b/MCP/tools/migrations/migrations_update_import.go new file mode 100644 index 0000000..673199e --- /dev/null +++ b/MCP/tools/migrations/migrations_update_import.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Migrations_update_importHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/import", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Import + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateMigrations_update_importTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_import", + mcp.WithDescription("Update an import"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("vcs", mcp.Description("Input parameter: The type of version control system you are migrating from.")), + mcp.WithString("vcs_password", mcp.Description("Input parameter: The password to provide to the originating repository.")), + mcp.WithString("vcs_username", mcp.Description("Input parameter: The username to provide to the originating repository.")), + mcp.WithString("tfvc_project", mcp.Description("Input parameter: For a tfvc import, the name of the project that is being imported.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Migrations_update_importHandler(cfg), + } +} diff --git a/MCP/tools/oidc/oidc_get_oidc_custom_sub_template_for_org.go b/MCP/tools/oidc/oidc_get_oidc_custom_sub_template_for_org.go new file mode 100644 index 0000000..0d85d26 --- /dev/null +++ b/MCP/tools/oidc/oidc_get_oidc_custom_sub_template_for_org.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Oidc_get_oidc_custom_sub_template_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/oidc/customization/sub", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOidc_get_oidc_custom_sub_template_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_actions_oidc_customization_sub", + mcp.WithDescription("Get the customization template for an OIDC subject claim for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Oidc_get_oidc_custom_sub_template_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/oidc/oidc_update_oidc_custom_sub_template_for_org.go b/MCP/tools/oidc/oidc_update_oidc_custom_sub_template_for_org.go new file mode 100644 index 0000000..c0f825f --- /dev/null +++ b/MCP/tools/oidc/oidc_update_oidc_custom_sub_template_for_org.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Oidc_update_oidc_custom_sub_template_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/actions/oidc/customization/sub", cfg.BaseURL, org) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOidc_update_oidc_custom_sub_template_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_actions_oidc_customization_sub", + mcp.WithDescription("Set the customization template for an OIDC subject claim for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("include_claim_keys", mcp.Required(), mcp.Description("Input parameter: Array of unique strings. Each claim key can only contain alphanumeric characters and underscores.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Oidc_update_oidc_custom_sub_template_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_route_stats_by_actor.go b/MCP/tools/orgs/api_insights_get_route_stats_by_actor.go new file mode 100644 index 0000000..440bf89 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_route_stats_by_actor.go @@ -0,0 +1,129 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_route_stats_by_actorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + actor_typeVal, ok := args["actor_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: actor_type"), nil + } + actor_type, ok := actor_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: actor_type"), nil + } + actor_idVal, ok := args["actor_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: actor_id"), nil + } + actor_id, ok := actor_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: actor_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["api_route_substring"]; ok { + queryParams = append(queryParams, fmt.Sprintf("api_route_substring=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/route-stats/%s/%s%s", cfg.BaseURL, org, actor_type, actor_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_route_stats_by_actorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_route-stats_actor_type_actor_id", + mcp.WithDescription("Get route stats by actor"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("actor_type", mcp.Required(), mcp.Description("The type of the actor")), + mcp.WithNumber("actor_id", mcp.Required(), mcp.Description("The ID of the actor")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithArray("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("api_route_substring", mcp.Description("Providing a substring will filter results where the API route contains the substring. This is a case-insensitive search.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_route_stats_by_actorHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_subject_stats.go b/MCP/tools/orgs/api_insights_get_subject_stats.go new file mode 100644 index 0000000..905d218 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_subject_stats.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_subject_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["subject_name_substring"]; ok { + queryParams = append(queryParams, fmt.Sprintf("subject_name_substring=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/subject-stats%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_subject_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_subject-stats", + mcp.WithDescription("Get subject stats"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithArray("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("subject_name_substring", mcp.Description("Providing a substring will filter results where the subject name contains the substring. This is a case-insensitive search.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_subject_statsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_summary_stats.go b/MCP/tools/orgs/api_insights_get_summary_stats.go new file mode 100644 index 0000000..eb87ccd --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_summary_stats.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_summary_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/summary-stats%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_summary_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_summary-stats", + mcp.WithDescription("Get summary stats"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_summary_statsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_summary_stats_by_actor.go b/MCP/tools/orgs/api_insights_get_summary_stats_by_actor.go new file mode 100644 index 0000000..62974dd --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_summary_stats_by_actor.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_summary_stats_by_actorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + actor_typeVal, ok := args["actor_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: actor_type"), nil + } + actor_type, ok := actor_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: actor_type"), nil + } + actor_idVal, ok := args["actor_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: actor_id"), nil + } + actor_id, ok := actor_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: actor_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/summary-stats/%s/%s%s", cfg.BaseURL, org, actor_type, actor_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_summary_stats_by_actorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_summary-stats_actor_type_actor_id", + mcp.WithDescription("Get summary stats by actor"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("actor_type", mcp.Required(), mcp.Description("The type of the actor")), + mcp.WithNumber("actor_id", mcp.Required(), mcp.Description("The ID of the actor")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_summary_stats_by_actorHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_summary_stats_by_user.go b/MCP/tools/orgs/api_insights_get_summary_stats_by_user.go new file mode 100644 index 0000000..fe82fa6 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_summary_stats_by_user.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_summary_stats_by_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + user_idVal, ok := args["user_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: user_id"), nil + } + user_id, ok := user_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: user_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/summary-stats/users/%s%s", cfg.BaseURL, org, user_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_summary_stats_by_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_summary-stats_users_user_id", + mcp.WithDescription("Get summary stats by user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("user_id", mcp.Required(), mcp.Description("The ID of the user to query for stats")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_summary_stats_by_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_time_stats.go b/MCP/tools/orgs/api_insights_get_time_stats.go new file mode 100644 index 0000000..1d806b1 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_time_stats.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_time_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + if val, ok := args["timestamp_increment"]; ok { + queryParams = append(queryParams, fmt.Sprintf("timestamp_increment=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/time-stats%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_time_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_time-stats", + mcp.WithDescription("Get time stats"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("timestamp_increment", mcp.Required(), mcp.Description("The increment of time used to breakdown the query results (5m, 10m, 1h, etc.)")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_time_statsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_time_stats_by_actor.go b/MCP/tools/orgs/api_insights_get_time_stats_by_actor.go new file mode 100644 index 0000000..5aa0440 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_time_stats_by_actor.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_time_stats_by_actorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + actor_typeVal, ok := args["actor_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: actor_type"), nil + } + actor_type, ok := actor_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: actor_type"), nil + } + actor_idVal, ok := args["actor_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: actor_id"), nil + } + actor_id, ok := actor_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: actor_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + if val, ok := args["timestamp_increment"]; ok { + queryParams = append(queryParams, fmt.Sprintf("timestamp_increment=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/time-stats/%s/%s%s", cfg.BaseURL, org, actor_type, actor_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_time_stats_by_actorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_time-stats_actor_type_actor_id", + mcp.WithDescription("Get time stats by actor"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("actor_type", mcp.Required(), mcp.Description("The type of the actor")), + mcp.WithNumber("actor_id", mcp.Required(), mcp.Description("The ID of the actor")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("timestamp_increment", mcp.Required(), mcp.Description("The increment of time used to breakdown the query results (5m, 10m, 1h, etc.)")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_time_stats_by_actorHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_time_stats_by_user.go b/MCP/tools/orgs/api_insights_get_time_stats_by_user.go new file mode 100644 index 0000000..7c1e0b0 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_time_stats_by_user.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_time_stats_by_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + user_idVal, ok := args["user_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: user_id"), nil + } + user_id, ok := user_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: user_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + if val, ok := args["timestamp_increment"]; ok { + queryParams = append(queryParams, fmt.Sprintf("timestamp_increment=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/time-stats/users/%s%s", cfg.BaseURL, org, user_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_time_stats_by_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_time-stats_users_user_id", + mcp.WithDescription("Get time stats by user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("user_id", mcp.Required(), mcp.Description("The ID of the user to query for stats")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("timestamp_increment", mcp.Required(), mcp.Description("The increment of time used to breakdown the query results (5m, 10m, 1h, etc.)")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_time_stats_by_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/api_insights_get_user_stats.go b/MCP/tools/orgs/api_insights_get_user_stats.go new file mode 100644 index 0000000..e3f2801 --- /dev/null +++ b/MCP/tools/orgs/api_insights_get_user_stats.go @@ -0,0 +1,120 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Api_insights_get_user_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + user_idVal, ok := args["user_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: user_id"), nil + } + user_id, ok := user_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: user_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["min_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("min_timestamp=%v", val)) + } + if val, ok := args["max_timestamp"]; ok { + queryParams = append(queryParams, fmt.Sprintf("max_timestamp=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["actor_name_substring"]; ok { + queryParams = append(queryParams, fmt.Sprintf("actor_name_substring=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/insights/api/user-stats/%s%s", cfg.BaseURL, org, user_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateApi_insights_get_user_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_insights_api_user-stats_user_id", + mcp.WithDescription("Get user stats"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("user_id", mcp.Required(), mcp.Description("The ID of the user to query for stats")), + mcp.WithString("min_timestamp", mcp.Required(), mcp.Description("The minimum timestamp to query for stats. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("max_timestamp", mcp.Description("The maximum timestamp to query for stats. Defaults to the time 30 days ago. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithArray("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("actor_name_substring", mcp.Description("Providing a substring will filter results where the actor name contains the substring. This is a case-insensitive search.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Api_insights_get_user_statsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_add_security_manager_team.go b/MCP/tools/orgs/orgs_add_security_manager_team.go new file mode 100644 index 0000000..c140f1d --- /dev/null +++ b/MCP/tools/orgs/orgs_add_security_manager_team.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_add_security_manager_teamHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + url := fmt.Sprintf("%s/orgs/%s/security-managers/teams/%s", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_add_security_manager_teamTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_security-managers_teams_team_slug", + mcp.WithDescription("Add a security manager team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_add_security_manager_teamHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_assign_team_to_org_role.go b/MCP/tools/orgs/orgs_assign_team_to_org_role.go new file mode 100644 index 0000000..b0112d5 --- /dev/null +++ b/MCP/tools/orgs/orgs_assign_team_to_org_role.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_assign_team_to_org_roleHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/teams/%s/%s", cfg.BaseURL, org, team_slug, role_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_assign_team_to_org_roleTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_organization-roles_teams_team_slug_role_id", + mcp.WithDescription("Assign an organization role to a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_assign_team_to_org_roleHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_assign_user_to_org_role.go b/MCP/tools/orgs/orgs_assign_user_to_org_role.go new file mode 100644 index 0000000..187be59 --- /dev/null +++ b/MCP/tools/orgs/orgs_assign_user_to_org_role.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_assign_user_to_org_roleHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/users/%s/%s", cfg.BaseURL, org, username, role_id) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_assign_user_to_org_roleTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_organization-roles_users_username_role_id", + mcp.WithDescription("Assign an organization role to a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_assign_user_to_org_roleHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_block_user.go b/MCP/tools/orgs/orgs_block_user.go new file mode 100644 index 0000000..e3afbd4 --- /dev/null +++ b/MCP/tools/orgs/orgs_block_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_block_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/blocks/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_block_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_blocks_username", + mcp.WithDescription("Block a user from an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_block_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_cancel_invitation.go b/MCP/tools/orgs/orgs_cancel_invitation.go new file mode 100644 index 0000000..631bc3f --- /dev/null +++ b/MCP/tools/orgs/orgs_cancel_invitation.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_cancel_invitationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + invitation_idVal, ok := args["invitation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: invitation_id"), nil + } + invitation_id, ok := invitation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: invitation_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/invitations/%s", cfg.BaseURL, org, invitation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_cancel_invitationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_invitations_invitation_id", + mcp.WithDescription("Cancel an organization invitation"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("invitation_id", mcp.Required(), mcp.Description("The unique identifier of the invitation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_cancel_invitationHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_check_blocked_user.go b/MCP/tools/orgs/orgs_check_blocked_user.go new file mode 100644 index 0000000..72fe493 --- /dev/null +++ b/MCP/tools/orgs/orgs_check_blocked_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_check_blocked_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/blocks/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_check_blocked_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_blocks_username", + mcp.WithDescription("Check if a user is blocked by an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_check_blocked_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_check_membership_for_user.go b/MCP/tools/orgs/orgs_check_membership_for_user.go new file mode 100644 index 0000000..d28b350 --- /dev/null +++ b/MCP/tools/orgs/orgs_check_membership_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_check_membership_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/members/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_check_membership_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_members_username", + mcp.WithDescription("Check organization membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_check_membership_for_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_check_public_membership_for_user.go b/MCP/tools/orgs/orgs_check_public_membership_for_user.go new file mode 100644 index 0000000..ecbca4f --- /dev/null +++ b/MCP/tools/orgs/orgs_check_public_membership_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_check_public_membership_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/public_members/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_check_public_membership_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_public_members_username", + mcp.WithDescription("Check public organization membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_check_public_membership_for_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_convert_member_to_outside_collaborator.go b/MCP/tools/orgs/orgs_convert_member_to_outside_collaborator.go new file mode 100644 index 0000000..7d12e16 --- /dev/null +++ b/MCP/tools/orgs/orgs_convert_member_to_outside_collaborator.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_convert_member_to_outside_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/outside_collaborators/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_convert_member_to_outside_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_outside_collaborators_username", + mcp.WithDescription("Convert an organization member to outside collaborator"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithBoolean("async", mcp.Description("Input parameter: When set to `true`, the request will be performed asynchronously. Returns a 202 status code when the job is successfully queued.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_convert_member_to_outside_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_create_invitation.go b/MCP/tools/orgs/orgs_create_invitation.go new file mode 100644 index 0000000..93c818b --- /dev/null +++ b/MCP/tools/orgs/orgs_create_invitation.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_create_invitationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/invitations", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_create_invitationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_invitations", + mcp.WithDescription("Create an organization invitation"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("email", mcp.Description("Input parameter: **Required unless you provide `invitee_id`**. Email address of the person you are inviting, which can be an existing GitHub user.")), + mcp.WithNumber("invitee_id", mcp.Description("Input parameter: **Required unless you provide `email`**. GitHub user ID for the person you are inviting.")), + mcp.WithString("role", mcp.Description("Input parameter: The role for the new member. \n * `admin` - Organization owners with full administrative rights to the organization and complete access to all repositories and teams. \n * `direct_member` - Non-owner organization members with ability to see other members and join teams by invitation. \n * `billing_manager` - Non-owner organization members with ability to manage the billing settings of your organization. \n * `reinstate` - The previous role assigned to the invitee before they were removed from your organization. Can be one of the roles listed above. Only works if the invitee was previously part of your organization.")), + mcp.WithArray("team_ids", mcp.Description("Input parameter: Specify IDs for the teams you want to invite new members to.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_create_invitationHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_create_issue_type.go b/MCP/tools/orgs/orgs_create_issue_type.go new file mode 100644 index 0000000..52bc327 --- /dev/null +++ b/MCP/tools/orgs/orgs_create_issue_type.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_create_issue_typeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/issue-types", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_create_issue_typeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_issue-types", + mcp.WithDescription("Create issue type for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("color", mcp.Description("Input parameter: Color for the issue type.")), + mcp.WithString("description", mcp.Description("Input parameter: Description of the issue type.")), + mcp.WithBoolean("is_enabled", mcp.Required(), mcp.Description("Input parameter: Whether or not the issue type is enabled at the organization level.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the issue type.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_create_issue_typeHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_create_or_update_custom_properties.go b/MCP/tools/orgs/orgs_create_or_update_custom_properties.go new file mode 100644 index 0000000..a03cf8e --- /dev/null +++ b/MCP/tools/orgs/orgs_create_or_update_custom_properties.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_create_or_update_custom_propertiesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/properties/schema", cfg.BaseURL, org) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_create_or_update_custom_propertiesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_properties_schema", + mcp.WithDescription("Create or update custom properties for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("properties", mcp.Required(), mcp.Description("Input parameter: The array of custom properties to create or update.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_create_or_update_custom_propertiesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_create_or_update_custom_properties_values_for_repos.go b/MCP/tools/orgs/orgs_create_or_update_custom_properties_values_for_repos.go new file mode 100644 index 0000000..ce678e9 --- /dev/null +++ b/MCP/tools/orgs/orgs_create_or_update_custom_properties_values_for_repos.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_create_or_update_custom_properties_values_for_reposHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/properties/values", cfg.BaseURL, org) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_create_or_update_custom_properties_values_for_reposTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_properties_values", + mcp.WithDescription("Create or update custom property values for organization repositories"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("properties", mcp.Required(), mcp.Description("Input parameter: List of custom property names and associated values to apply to the repositories.")), + mcp.WithArray("repository_names", mcp.Required(), mcp.Description("Input parameter: The names of repositories that the custom property values will be applied to.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_create_or_update_custom_properties_values_for_reposHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_create_or_update_custom_property.go b/MCP/tools/orgs/orgs_create_or_update_custom_property.go new file mode 100644 index 0000000..59e48f4 --- /dev/null +++ b/MCP/tools/orgs/orgs_create_or_update_custom_property.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_create_or_update_custom_propertyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + custom_property_nameVal, ok := args["custom_property_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: custom_property_name"), nil + } + custom_property_name, ok := custom_property_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: custom_property_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/properties/schema/%s", cfg.BaseURL, org, custom_property_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_create_or_update_custom_propertyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_properties_schema_custom_property_name", + mcp.WithDescription("Create or update a custom property for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("custom_property_name", mcp.Required(), mcp.Description("The custom property name")), + mcp.WithString("description", mcp.Description("Input parameter: Short description of the property")), + mcp.WithBoolean("required", mcp.Description("Input parameter: Whether the property is required.")), + mcp.WithString("value_type", mcp.Required(), mcp.Description("Input parameter: The type of the value for the property")), + mcp.WithString("values_editable_by", mcp.Description("Input parameter: Who can edit the values of the property")), + mcp.WithArray("allowed_values", mcp.Description("Input parameter: An ordered list of the allowed values of the property.\nThe property can have up to 200 allowed values.")), + mcp.WithString("default_value", mcp.Description("Input parameter: Default value of the property")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_create_or_update_custom_propertyHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_create_webhook.go b/MCP/tools/orgs/orgs_create_webhook.go new file mode 100644 index 0000000..49f0961 --- /dev/null +++ b/MCP/tools/orgs/orgs_create_webhook.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_create_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_create_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_hooks", + mcp.WithDescription("Create an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithBoolean("active", mcp.Description("Input parameter: Determines if notifications are sent when the webhook is triggered. Set to `true` to send notifications.")), + mcp.WithObject("config", mcp.Required(), mcp.Description("Input parameter: Key/value pairs to provide settings for this webhook.")), + mcp.WithArray("events", mcp.Description("Input parameter: Determines what [events](https://docs.github.com/webhooks/event-payloads) the hook is triggered for. Set to `[\"*\"]` to receive all possible events.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Must be passed as \"web\".")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_create_webhookHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_delete.go b/MCP/tools/orgs/orgs_delete.go new file mode 100644 index 0000000..0594557 --- /dev/null +++ b/MCP/tools/orgs/orgs_delete.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_deleteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s", cfg.BaseURL, org) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_deleteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org", + mcp.WithDescription("Delete an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_deleteHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_delete_attestations_bulk.go b/MCP/tools/orgs/orgs_delete_attestations_bulk.go new file mode 100644 index 0000000..e46c06e --- /dev/null +++ b/MCP/tools/orgs/orgs_delete_attestations_bulk.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_delete_attestations_bulkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/attestations/delete-request", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_delete_attestations_bulkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_attestations_delete-request", + mcp.WithDescription("Delete attestations in bulk"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_delete_attestations_bulkHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_delete_attestations_by_id.go b/MCP/tools/orgs/orgs_delete_attestations_by_id.go new file mode 100644 index 0000000..016a439 --- /dev/null +++ b/MCP/tools/orgs/orgs_delete_attestations_by_id.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_delete_attestations_by_idHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + attestation_idVal, ok := args["attestation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: attestation_id"), nil + } + attestation_id, ok := attestation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: attestation_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/attestations/%s", cfg.BaseURL, org, attestation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_delete_attestations_by_idTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_attestations_attestation_id", + mcp.WithDescription("Delete attestations by ID"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("attestation_id", mcp.Required(), mcp.Description("Attestation ID")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_delete_attestations_by_idHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_delete_attestations_by_subject_digest.go b/MCP/tools/orgs/orgs_delete_attestations_by_subject_digest.go new file mode 100644 index 0000000..e99cf3a --- /dev/null +++ b/MCP/tools/orgs/orgs_delete_attestations_by_subject_digest.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_delete_attestations_by_subject_digestHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + subject_digestVal, ok := args["subject_digest"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: subject_digest"), nil + } + subject_digest, ok := subject_digestVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: subject_digest"), nil + } + url := fmt.Sprintf("%s/orgs/%s/attestations/digest/%s", cfg.BaseURL, org, subject_digest) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_delete_attestations_by_subject_digestTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_attestations_digest_subject_digest", + mcp.WithDescription("Delete attestations by subject digest"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("subject_digest", mcp.Required(), mcp.Description("Subject Digest")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_delete_attestations_by_subject_digestHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_delete_issue_type.go b/MCP/tools/orgs/orgs_delete_issue_type.go new file mode 100644 index 0000000..a9224e4 --- /dev/null +++ b/MCP/tools/orgs/orgs_delete_issue_type.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_delete_issue_typeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + issue_type_idVal, ok := args["issue_type_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_type_id"), nil + } + issue_type_id, ok := issue_type_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_type_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/issue-types/%s", cfg.BaseURL, org, issue_type_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_delete_issue_typeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_issue-types_issue_type_id", + mcp.WithDescription("Delete issue type for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("issue_type_id", mcp.Required(), mcp.Description("The unique identifier of the issue type.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_delete_issue_typeHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_delete_webhook.go b/MCP/tools/orgs/orgs_delete_webhook.go new file mode 100644 index 0000000..2700221 --- /dev/null +++ b/MCP/tools/orgs/orgs_delete_webhook.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_delete_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s", cfg.BaseURL, org, hook_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_delete_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_hooks_hook_id", + mcp.WithDescription("Delete an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_delete_webhookHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_enable_or_disable_security_product_on_all_org_repos.go b/MCP/tools/orgs/orgs_enable_or_disable_security_product_on_all_org_repos.go new file mode 100644 index 0000000..2f21de9 --- /dev/null +++ b/MCP/tools/orgs/orgs_enable_or_disable_security_product_on_all_org_repos.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_enable_or_disable_security_product_on_all_org_reposHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + security_productVal, ok := args["security_product"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: security_product"), nil + } + security_product, ok := security_productVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: security_product"), nil + } + enablementVal, ok := args["enablement"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enablement"), nil + } + enablement, ok := enablementVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enablement"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/%s/%s", cfg.BaseURL, org, security_product, enablement) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_enable_or_disable_security_product_on_all_org_reposTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_security_product_enablement", + mcp.WithDescription("Enable or disable a security feature for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("security_product", mcp.Required(), mcp.Description("The security feature to enable or disable.")), + mcp.WithString("enablement", mcp.Required(), mcp.Description("The action to take.\n\n`enable_all` means to enable the specified security feature for all repositories in the organization.\n`disable_all` means to disable the specified security feature for all repositories in the organization.")), + mcp.WithString("query_suite", mcp.Description("Input parameter: CodeQL query suite to be used. If you specify the `query_suite` parameter, the default setup will be configured with this query suite only on all repositories that didn't have default setup already configured. It will not change the query suite on repositories that already have default setup configured.\nIf you don't specify any `query_suite` in your request, the preferred query suite of the organization will be applied.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_enable_or_disable_security_product_on_all_org_reposHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get.go b/MCP/tools/orgs/orgs_get.go new file mode 100644 index 0000000..85661e0 --- /dev/null +++ b/MCP/tools/orgs/orgs_get.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org", + mcp.WithDescription("Get an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_getHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_all_custom_properties.go b/MCP/tools/orgs/orgs_get_all_custom_properties.go new file mode 100644 index 0000000..7802337 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_all_custom_properties.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_all_custom_propertiesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/properties/schema", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_all_custom_propertiesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_properties_schema", + mcp.WithDescription("Get all custom properties for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_all_custom_propertiesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_custom_property.go b/MCP/tools/orgs/orgs_get_custom_property.go new file mode 100644 index 0000000..00b7c61 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_custom_property.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_custom_propertyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + custom_property_nameVal, ok := args["custom_property_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: custom_property_name"), nil + } + custom_property_name, ok := custom_property_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: custom_property_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/properties/schema/%s", cfg.BaseURL, org, custom_property_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_custom_propertyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_properties_schema_custom_property_name", + mcp.WithDescription("Get a custom property for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("custom_property_name", mcp.Required(), mcp.Description("The custom property name")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_custom_propertyHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_membership_for_authenticated_user.go b/MCP/tools/orgs/orgs_get_membership_for_authenticated_user.go new file mode 100644 index 0000000..844ca99 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_membership_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_membership_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/user/memberships/orgs/%s", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_membership_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_memberships_orgs_org", + mcp.WithDescription("Get an organization membership for the authenticated user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_membership_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_membership_for_user.go b/MCP/tools/orgs/orgs_get_membership_for_user.go new file mode 100644 index 0000000..9a35473 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_membership_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_membership_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/memberships/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_membership_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_memberships_username", + mcp.WithDescription("Get organization membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_membership_for_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_org_role.go b/MCP/tools/orgs/orgs_get_org_role.go new file mode 100644 index 0000000..5eb4c08 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_org_role.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_org_roleHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/%s", cfg.BaseURL, org, role_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_org_roleTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_organization-roles_role_id", + mcp.WithDescription("Get an organization role"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_org_roleHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_org_ruleset_history.go b/MCP/tools/orgs/orgs_get_org_ruleset_history.go new file mode 100644 index 0000000..f576b25 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_org_ruleset_history.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_org_ruleset_historyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/%s/history%s", cfg.BaseURL, org, ruleset_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_org_ruleset_historyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_rulesets_ruleset_id_history", + mcp.WithDescription("Get organization ruleset history"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_org_ruleset_historyHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_org_ruleset_version.go b/MCP/tools/orgs/orgs_get_org_ruleset_version.go new file mode 100644 index 0000000..0fdeb62 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_org_ruleset_version.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_org_ruleset_versionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + version_idVal, ok := args["version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: version_id"), nil + } + version_id, ok := version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: version_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/%s/history/%s", cfg.BaseURL, org, ruleset_id, version_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_org_ruleset_versionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_rulesets_ruleset_id_history_version_id", + mcp.WithDescription("Get organization ruleset version"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + mcp.WithNumber("version_id", mcp.Required(), mcp.Description("The ID of the version")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_org_ruleset_versionHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_webhook.go b/MCP/tools/orgs/orgs_get_webhook.go new file mode 100644 index 0000000..e5735db --- /dev/null +++ b/MCP/tools/orgs/orgs_get_webhook.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s", cfg.BaseURL, org, hook_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_hooks_hook_id", + mcp.WithDescription("Get an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_webhookHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_webhook_config_for_org.go b/MCP/tools/orgs/orgs_get_webhook_config_for_org.go new file mode 100644 index 0000000..f87b9f6 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_webhook_config_for_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_webhook_config_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s/config", cfg.BaseURL, org, hook_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_webhook_config_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_hooks_hook_id_config", + mcp.WithDescription("Get a webhook configuration for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_webhook_config_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_get_webhook_delivery.go b/MCP/tools/orgs/orgs_get_webhook_delivery.go new file mode 100644 index 0000000..fb511c1 --- /dev/null +++ b/MCP/tools/orgs/orgs_get_webhook_delivery.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_get_webhook_deliveryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + delivery_idVal, ok := args["delivery_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: delivery_id"), nil + } + delivery_id, ok := delivery_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: delivery_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s/deliveries/%s", cfg.BaseURL, org, hook_id, delivery_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_get_webhook_deliveryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_hooks_hook_id_deliveries_delivery_id", + mcp.WithDescription("Get a webhook delivery for an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithNumber("delivery_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_get_webhook_deliveryHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list.go b/MCP/tools/orgs/orgs_list.go new file mode 100644 index 0000000..a0d52fa --- /dev/null +++ b/MCP/tools/orgs/orgs_list.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/organizations%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_organizations", + mcp.WithDescription("List organizations"), + mcp.WithNumber("since", mcp.Description("An organization ID. Only return organizations with an ID greater than this ID.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_listHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_app_installations.go b/MCP/tools/orgs/orgs_list_app_installations.go new file mode 100644 index 0000000..36f8ce1 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_app_installations.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_app_installationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/installations%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_app_installationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_installations", + mcp.WithDescription("List app installations for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_app_installationsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_attestations.go b/MCP/tools/orgs/orgs_list_attestations.go new file mode 100644 index 0000000..1d0fd51 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_attestations.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_attestationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + subject_digestVal, ok := args["subject_digest"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: subject_digest"), nil + } + subject_digest, ok := subject_digestVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: subject_digest"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["predicate_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("predicate_type=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/attestations/%s%s", cfg.BaseURL, org, subject_digest, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_attestationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_attestations_subject_digest", + mcp.WithDescription("List attestations"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("subject_digest", mcp.Required(), mcp.Description("The parameter should be set to the attestation's subject's SHA256 digest, in the form `sha256:HEX_DIGEST`.")), + mcp.WithString("predicate_type", mcp.Description("Optional filter for fetching attestations with a given predicate type.\nThis option accepts `provenance`, `sbom`, or freeform text for custom predicate types.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_attestationsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_attestations_bulk.go b/MCP/tools/orgs/orgs_list_attestations_bulk.go new file mode 100644 index 0000000..6411699 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_attestations_bulk.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_attestations_bulkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/attestations/bulk-list%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_attestations_bulkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_attestations_bulk-list", + mcp.WithDescription("List attestations by bulk subject digests"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("predicate_type", mcp.Description("Input parameter: Optional filter for fetching attestations with a given predicate type.\nThis option accepts `provenance`, `sbom`, or freeform text for custom predicate types.")), + mcp.WithArray("subject_digests", mcp.Required(), mcp.Description("Input parameter: List of subject digests to fetch attestations for.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_attestations_bulkHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_blocked_users.go b/MCP/tools/orgs/orgs_list_blocked_users.go new file mode 100644 index 0000000..a840186 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_blocked_users.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_blocked_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/blocks%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_blocked_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_blocks", + mcp.WithDescription("List users blocked by an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_blocked_usersHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_custom_properties_values_for_repos.go b/MCP/tools/orgs/orgs_list_custom_properties_values_for_repos.go new file mode 100644 index 0000000..9b5ed91 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_custom_properties_values_for_repos.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_custom_properties_values_for_reposHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["repository_query"]; ok { + queryParams = append(queryParams, fmt.Sprintf("repository_query=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/properties/values%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_custom_properties_values_for_reposTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_properties_values", + mcp.WithDescription("List custom property values for organization repositories"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("repository_query", mcp.Description("Finds repositories in the organization with a query containing one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query). See \"[Searching for repositories](https://docs.github.com/articles/searching-for-repositories/)\" for a detailed list of qualifiers.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_custom_properties_values_for_reposHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_failed_invitations.go b/MCP/tools/orgs/orgs_list_failed_invitations.go new file mode 100644 index 0000000..adee7dc --- /dev/null +++ b/MCP/tools/orgs/orgs_list_failed_invitations.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_failed_invitationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/failed_invitations%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_failed_invitationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_failed_invitations", + mcp.WithDescription("List failed organization invitations"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_failed_invitationsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_for_authenticated_user.go b/MCP/tools/orgs/orgs_list_for_authenticated_user.go new file mode 100644 index 0000000..3dbee5c --- /dev/null +++ b/MCP/tools/orgs/orgs_list_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/orgs%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_orgs", + mcp.WithDescription("List organizations for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_for_user.go b/MCP/tools/orgs/orgs_list_for_user.go new file mode 100644 index 0000000..66daec0 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/orgs%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_orgs", + mcp.WithDescription("List organizations for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_for_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_invitation_teams.go b/MCP/tools/orgs/orgs_list_invitation_teams.go new file mode 100644 index 0000000..ae47a9f --- /dev/null +++ b/MCP/tools/orgs/orgs_list_invitation_teams.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_invitation_teamsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + invitation_idVal, ok := args["invitation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: invitation_id"), nil + } + invitation_id, ok := invitation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: invitation_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/invitations/%s/teams%s", cfg.BaseURL, org, invitation_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_invitation_teamsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_invitations_invitation_id_teams", + mcp.WithDescription("List organization invitation teams"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("invitation_id", mcp.Required(), mcp.Description("The unique identifier of the invitation.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_invitation_teamsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_issue_types.go b/MCP/tools/orgs/orgs_list_issue_types.go new file mode 100644 index 0000000..3b9b4e0 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_issue_types.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_issue_typesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/issue-types", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_issue_typesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_issue-types", + mcp.WithDescription("List issue types for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_issue_typesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_members.go b/MCP/tools/orgs/orgs_list_members.go new file mode 100644 index 0000000..23251ea --- /dev/null +++ b/MCP/tools/orgs/orgs_list_members.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_membersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["role"]; ok { + queryParams = append(queryParams, fmt.Sprintf("role=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/members%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_membersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_members", + mcp.WithDescription("List organization members"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("filter", mcp.Description("Filter members returned in the list. `2fa_disabled` means that only members without [two-factor authentication](https://github.com/blog/1614-two-factor-authentication) enabled will be returned. `2fa_insecure` means that only members with [insecure 2FA methods](https://docs.github.com/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization#requiring-secure-methods-of-two-factor-authentication-in-your-organization) will be returned. These options are only available for organization owners.")), + mcp.WithString("role", mcp.Description("Filter members returned by their role.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_membersHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_memberships_for_authenticated_user.go b/MCP/tools/orgs/orgs_list_memberships_for_authenticated_user.go new file mode 100644 index 0000000..c286f7c --- /dev/null +++ b/MCP/tools/orgs/orgs_list_memberships_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_memberships_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/memberships/orgs%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_memberships_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_memberships_orgs", + mcp.WithDescription("List organization memberships for the authenticated user"), + mcp.WithString("state", mcp.Description("Indicates the state of the memberships to return. If not specified, the API returns both active and pending memberships.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_memberships_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_org_role_teams.go b/MCP/tools/orgs/orgs_list_org_role_teams.go new file mode 100644 index 0000000..70c41f8 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_org_role_teams.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_org_role_teamsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/%s/teams%s", cfg.BaseURL, org, role_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_org_role_teamsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_organization-roles_role_id_teams", + mcp.WithDescription("List teams that are assigned to an organization role"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_org_role_teamsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_org_role_users.go b/MCP/tools/orgs/orgs_list_org_role_users.go new file mode 100644 index 0000000..a65b384 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_org_role_users.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_org_role_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/%s/users%s", cfg.BaseURL, org, role_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_org_role_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_organization-roles_role_id_users", + mcp.WithDescription("List users that are assigned to an organization role"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_org_role_usersHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_org_roles.go b/MCP/tools/orgs/orgs_list_org_roles.go new file mode 100644 index 0000000..55ee7b8 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_org_roles.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_org_rolesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_org_rolesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_organization-roles", + mcp.WithDescription("Get all organization roles for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_org_rolesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_outside_collaborators.go b/MCP/tools/orgs/orgs_list_outside_collaborators.go new file mode 100644 index 0000000..b62a356 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_outside_collaborators.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_outside_collaboratorsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["filter"]; ok { + queryParams = append(queryParams, fmt.Sprintf("filter=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/outside_collaborators%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_outside_collaboratorsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_outside_collaborators", + mcp.WithDescription("List outside collaborators for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("filter", mcp.Description("Filter the list of outside collaborators. `2fa_disabled` means that only outside collaborators without [two-factor authentication](https://github.com/blog/1614-two-factor-authentication) enabled will be returned. `2fa_insecure` means that only outside collaborators with [insecure 2FA methods](https://docs.github.com/organizations/keeping-your-organization-secure/managing-two-factor-authentication-for-your-organization/requiring-two-factor-authentication-in-your-organization#requiring-secure-methods-of-two-factor-authentication-in-your-organization) will be returned.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_outside_collaboratorsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_pat_grant_repositories.go b/MCP/tools/orgs/orgs_list_pat_grant_repositories.go new file mode 100644 index 0000000..af81ae5 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_pat_grant_repositories.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_pat_grant_repositoriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + pat_idVal, ok := args["pat_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pat_id"), nil + } + pat_id, ok := pat_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pat_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-tokens/%s/repositories%s", cfg.BaseURL, org, pat_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_pat_grant_repositoriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_personal-access-tokens_pat_id_repositories", + mcp.WithDescription("List repositories a fine-grained personal access token has access to"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("pat_id", mcp.Required(), mcp.Description("Unique identifier of the fine-grained personal access token.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_pat_grant_repositoriesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_pat_grant_request_repositories.go b/MCP/tools/orgs/orgs_list_pat_grant_request_repositories.go new file mode 100644 index 0000000..fb380ab --- /dev/null +++ b/MCP/tools/orgs/orgs_list_pat_grant_request_repositories.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_pat_grant_request_repositoriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + pat_request_idVal, ok := args["pat_request_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pat_request_id"), nil + } + pat_request_id, ok := pat_request_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pat_request_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-token-requests/%s/repositories%s", cfg.BaseURL, org, pat_request_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_pat_grant_request_repositoriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_personal-access-token-requests_pat_request_id_repositories", + mcp.WithDescription("List repositories requested to be accessed by a fine-grained personal access token"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("pat_request_id", mcp.Required(), mcp.Description("Unique identifier of the request for access via fine-grained personal access token.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_pat_grant_request_repositoriesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_pat_grant_requests.go b/MCP/tools/orgs/orgs_list_pat_grant_requests.go new file mode 100644 index 0000000..c09596b --- /dev/null +++ b/MCP/tools/orgs/orgs_list_pat_grant_requests.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_pat_grant_requestsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["owner"]; ok { + queryParams = append(queryParams, fmt.Sprintf("owner=%v", val)) + } + if val, ok := args["repository"]; ok { + queryParams = append(queryParams, fmt.Sprintf("repository=%v", val)) + } + if val, ok := args["permission"]; ok { + queryParams = append(queryParams, fmt.Sprintf("permission=%v", val)) + } + if val, ok := args["last_used_before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last_used_before=%v", val)) + } + if val, ok := args["last_used_after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last_used_after=%v", val)) + } + if val, ok := args["token_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("token_id=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-token-requests%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_pat_grant_requestsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_personal-access-token-requests", + mcp.WithDescription("List requests to access organization resources with fine-grained personal access tokens"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithArray("owner", mcp.Description("A list of owner usernames to use to filter the results.")), + mcp.WithString("repository", mcp.Description("The name of the repository to use to filter the results.")), + mcp.WithString("permission", mcp.Description("The permission to use to filter the results.")), + mcp.WithString("last_used_before", mcp.Description("Only show fine-grained personal access tokens used before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("last_used_after", mcp.Description("Only show fine-grained personal access tokens used after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithArray("token_id", mcp.Description("The ID of the token")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_pat_grant_requestsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_pat_grants.go b/MCP/tools/orgs/orgs_list_pat_grants.go new file mode 100644 index 0000000..d97ab49 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_pat_grants.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_pat_grantsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["owner"]; ok { + queryParams = append(queryParams, fmt.Sprintf("owner=%v", val)) + } + if val, ok := args["repository"]; ok { + queryParams = append(queryParams, fmt.Sprintf("repository=%v", val)) + } + if val, ok := args["permission"]; ok { + queryParams = append(queryParams, fmt.Sprintf("permission=%v", val)) + } + if val, ok := args["last_used_before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last_used_before=%v", val)) + } + if val, ok := args["last_used_after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("last_used_after=%v", val)) + } + if val, ok := args["token_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("token_id=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-tokens%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_pat_grantsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_personal-access-tokens", + mcp.WithDescription("List fine-grained personal access tokens with access to organization resources"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("sort", mcp.Description("The property by which to sort the results.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithArray("owner", mcp.Description("A list of owner usernames to use to filter the results.")), + mcp.WithString("repository", mcp.Description("The name of the repository to use to filter the results.")), + mcp.WithString("permission", mcp.Description("The permission to use to filter the results.")), + mcp.WithString("last_used_before", mcp.Description("Only show fine-grained personal access tokens used before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("last_used_after", mcp.Description("Only show fine-grained personal access tokens used after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithArray("token_id", mcp.Description("The ID of the token")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_pat_grantsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_pending_invitations.go b/MCP/tools/orgs/orgs_list_pending_invitations.go new file mode 100644 index 0000000..5f97855 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_pending_invitations.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_pending_invitationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["role"]; ok { + queryParams = append(queryParams, fmt.Sprintf("role=%v", val)) + } + if val, ok := args["invitation_source"]; ok { + queryParams = append(queryParams, fmt.Sprintf("invitation_source=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/invitations%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_pending_invitationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_invitations", + mcp.WithDescription("List pending organization invitations"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("role", mcp.Description("Filter invitations by their member role.")), + mcp.WithString("invitation_source", mcp.Description("Filter invitations by their invitation source.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_pending_invitationsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_public_members.go b/MCP/tools/orgs/orgs_list_public_members.go new file mode 100644 index 0000000..72dcc9f --- /dev/null +++ b/MCP/tools/orgs/orgs_list_public_members.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_public_membersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/public_members%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_public_membersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_public_members", + mcp.WithDescription("List public organization members"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_public_membersHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_security_manager_teams.go b/MCP/tools/orgs/orgs_list_security_manager_teams.go new file mode 100644 index 0000000..2a6092f --- /dev/null +++ b/MCP/tools/orgs/orgs_list_security_manager_teams.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_security_manager_teamsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/security-managers", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_security_manager_teamsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_security-managers", + mcp.WithDescription("List security manager teams"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_security_manager_teamsHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_webhook_deliveries.go b/MCP/tools/orgs/orgs_list_webhook_deliveries.go new file mode 100644 index 0000000..35ea9f2 --- /dev/null +++ b/MCP/tools/orgs/orgs_list_webhook_deliveries.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_webhook_deliveriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["cursor"]; ok { + queryParams = append(queryParams, fmt.Sprintf("cursor=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s/deliveries%s", cfg.BaseURL, org, hook_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_webhook_deliveriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_hooks_hook_id_deliveries", + mcp.WithDescription("List deliveries for an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("cursor", mcp.Description("Used for pagination: the starting delivery from which the page of deliveries is fetched. Refer to the `link` header for the next and previous page cursors.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_webhook_deliveriesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_list_webhooks.go b/MCP/tools/orgs/orgs_list_webhooks.go new file mode 100644 index 0000000..0299c5c --- /dev/null +++ b/MCP/tools/orgs/orgs_list_webhooks.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_list_webhooksHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/hooks%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_list_webhooksTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_hooks", + mcp.WithDescription("List organization webhooks"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_list_webhooksHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_ping_webhook.go b/MCP/tools/orgs/orgs_ping_webhook.go new file mode 100644 index 0000000..b13f8c2 --- /dev/null +++ b/MCP/tools/orgs/orgs_ping_webhook.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_ping_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s/pings", cfg.BaseURL, org, hook_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_ping_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_hooks_hook_id_pings", + mcp.WithDescription("Ping an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_ping_webhookHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_redeliver_webhook_delivery.go b/MCP/tools/orgs/orgs_redeliver_webhook_delivery.go new file mode 100644 index 0000000..c77c6db --- /dev/null +++ b/MCP/tools/orgs/orgs_redeliver_webhook_delivery.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_redeliver_webhook_deliveryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + delivery_idVal, ok := args["delivery_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: delivery_id"), nil + } + delivery_id, ok := delivery_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: delivery_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s/deliveries/%s/attempts", cfg.BaseURL, org, hook_id, delivery_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_redeliver_webhook_deliveryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_hooks_hook_id_deliveries_delivery_id_attempts", + mcp.WithDescription("Redeliver a delivery for an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithNumber("delivery_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_redeliver_webhook_deliveryHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_remove_custom_property.go b/MCP/tools/orgs/orgs_remove_custom_property.go new file mode 100644 index 0000000..723b74a --- /dev/null +++ b/MCP/tools/orgs/orgs_remove_custom_property.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_remove_custom_propertyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + custom_property_nameVal, ok := args["custom_property_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: custom_property_name"), nil + } + custom_property_name, ok := custom_property_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: custom_property_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/properties/schema/%s", cfg.BaseURL, org, custom_property_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_remove_custom_propertyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_properties_schema_custom_property_name", + mcp.WithDescription("Remove a custom property for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("custom_property_name", mcp.Required(), mcp.Description("The custom property name")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_remove_custom_propertyHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_remove_member.go b/MCP/tools/orgs/orgs_remove_member.go new file mode 100644 index 0000000..52667a9 --- /dev/null +++ b/MCP/tools/orgs/orgs_remove_member.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_remove_memberHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/members/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_remove_memberTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_members_username", + mcp.WithDescription("Remove an organization member"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_remove_memberHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_remove_membership_for_user.go b/MCP/tools/orgs/orgs_remove_membership_for_user.go new file mode 100644 index 0000000..1ccfda7 --- /dev/null +++ b/MCP/tools/orgs/orgs_remove_membership_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_remove_membership_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/memberships/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_remove_membership_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_memberships_username", + mcp.WithDescription("Remove organization membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_remove_membership_for_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_remove_outside_collaborator.go b/MCP/tools/orgs/orgs_remove_outside_collaborator.go new file mode 100644 index 0000000..38c93ca --- /dev/null +++ b/MCP/tools/orgs/orgs_remove_outside_collaborator.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_remove_outside_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/outside_collaborators/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_remove_outside_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_outside_collaborators_username", + mcp.WithDescription("Remove outside collaborator from an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_remove_outside_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_remove_public_membership_for_authenticated_user.go b/MCP/tools/orgs/orgs_remove_public_membership_for_authenticated_user.go new file mode 100644 index 0000000..8f6057e --- /dev/null +++ b/MCP/tools/orgs/orgs_remove_public_membership_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_remove_public_membership_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/public_members/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_remove_public_membership_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_public_members_username", + mcp.WithDescription("Remove public organization membership for the authenticated user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_remove_public_membership_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_remove_security_manager_team.go b/MCP/tools/orgs/orgs_remove_security_manager_team.go new file mode 100644 index 0000000..514fb8f --- /dev/null +++ b/MCP/tools/orgs/orgs_remove_security_manager_team.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_remove_security_manager_teamHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + url := fmt.Sprintf("%s/orgs/%s/security-managers/teams/%s", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_remove_security_manager_teamTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_security-managers_teams_team_slug", + mcp.WithDescription("Remove a security manager team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_remove_security_manager_teamHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_review_pat_grant_request.go b/MCP/tools/orgs/orgs_review_pat_grant_request.go new file mode 100644 index 0000000..8672740 --- /dev/null +++ b/MCP/tools/orgs/orgs_review_pat_grant_request.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_review_pat_grant_requestHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + pat_request_idVal, ok := args["pat_request_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pat_request_id"), nil + } + pat_request_id, ok := pat_request_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pat_request_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-token-requests/%s", cfg.BaseURL, org, pat_request_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_review_pat_grant_requestTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_personal-access-token-requests_pat_request_id", + mcp.WithDescription("Review a request to access organization resources with a fine-grained personal access token"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("pat_request_id", mcp.Required(), mcp.Description("Unique identifier of the request for access via fine-grained personal access token.")), + mcp.WithString("action", mcp.Required(), mcp.Description("Input parameter: Action to apply to the request.")), + mcp.WithString("reason", mcp.Description("Input parameter: Reason for approving or denying the request. Max 1024 characters.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_review_pat_grant_requestHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_review_pat_grant_requests_in_bulk.go b/MCP/tools/orgs/orgs_review_pat_grant_requests_in_bulk.go new file mode 100644 index 0000000..09efdac --- /dev/null +++ b/MCP/tools/orgs/orgs_review_pat_grant_requests_in_bulk.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_review_pat_grant_requests_in_bulkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-token-requests", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_review_pat_grant_requests_in_bulkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_personal-access-token-requests", + mcp.WithDescription("Review requests to access organization resources with fine-grained personal access tokens"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("action", mcp.Required(), mcp.Description("Input parameter: Action to apply to the requests.")), + mcp.WithArray("pat_request_ids", mcp.Description("Input parameter: Unique identifiers of the requests for access via fine-grained personal access token. Must be formed of between 1 and 100 `pat_request_id` values.")), + mcp.WithString("reason", mcp.Description("Input parameter: Reason for approving or denying the requests. Max 1024 characters.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_review_pat_grant_requests_in_bulkHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_revoke_all_org_roles_team.go b/MCP/tools/orgs/orgs_revoke_all_org_roles_team.go new file mode 100644 index 0000000..035f1ac --- /dev/null +++ b/MCP/tools/orgs/orgs_revoke_all_org_roles_team.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_revoke_all_org_roles_teamHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/teams/%s", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_revoke_all_org_roles_teamTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_organization-roles_teams_team_slug", + mcp.WithDescription("Remove all organization roles for a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_revoke_all_org_roles_teamHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_revoke_all_org_roles_user.go b/MCP/tools/orgs/orgs_revoke_all_org_roles_user.go new file mode 100644 index 0000000..f958618 --- /dev/null +++ b/MCP/tools/orgs/orgs_revoke_all_org_roles_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_revoke_all_org_roles_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/users/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_revoke_all_org_roles_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_organization-roles_users_username", + mcp.WithDescription("Remove all organization roles for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_revoke_all_org_roles_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_revoke_org_role_team.go b/MCP/tools/orgs/orgs_revoke_org_role_team.go new file mode 100644 index 0000000..6ed7745 --- /dev/null +++ b/MCP/tools/orgs/orgs_revoke_org_role_team.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_revoke_org_role_teamHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/teams/%s/%s", cfg.BaseURL, org, team_slug, role_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_revoke_org_role_teamTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_organization-roles_teams_team_slug_role_id", + mcp.WithDescription("Remove an organization role from a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_revoke_org_role_teamHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_revoke_org_role_user.go b/MCP/tools/orgs/orgs_revoke_org_role_user.go new file mode 100644 index 0000000..d6b4d0e --- /dev/null +++ b/MCP/tools/orgs/orgs_revoke_org_role_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_revoke_org_role_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + role_idVal, ok := args["role_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: role_id"), nil + } + role_id, ok := role_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: role_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/organization-roles/users/%s/%s", cfg.BaseURL, org, username, role_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_revoke_org_role_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_organization-roles_users_username_role_id", + mcp.WithDescription("Remove an organization role from a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("role_id", mcp.Required(), mcp.Description("The unique identifier of the role.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_revoke_org_role_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_set_membership_for_user.go b/MCP/tools/orgs/orgs_set_membership_for_user.go new file mode 100644 index 0000000..baeb6ed --- /dev/null +++ b/MCP/tools/orgs/orgs_set_membership_for_user.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_set_membership_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/memberships/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_set_membership_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_memberships_username", + mcp.WithDescription("Set organization membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("role", mcp.Description("Input parameter: The role to give the user in the organization. Can be one of: \n * `admin` - The user will become an owner of the organization. \n * `member` - The user will become a non-owner member of the organization.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_set_membership_for_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_set_public_membership_for_authenticated_user.go b/MCP/tools/orgs/orgs_set_public_membership_for_authenticated_user.go new file mode 100644 index 0000000..e11053e --- /dev/null +++ b/MCP/tools/orgs/orgs_set_public_membership_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_set_public_membership_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/public_members/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_set_public_membership_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_public_members_username", + mcp.WithDescription("Set public organization membership for the authenticated user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_set_public_membership_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_unblock_user.go b/MCP/tools/orgs/orgs_unblock_user.go new file mode 100644 index 0000000..b3f5a99 --- /dev/null +++ b/MCP/tools/orgs/orgs_unblock_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_unblock_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/blocks/%s", cfg.BaseURL, org, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_unblock_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_blocks_username", + mcp.WithDescription("Unblock a user from an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_unblock_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update.go b/MCP/tools/orgs/orgs_update.go new file mode 100644 index 0000000..b861697 --- /dev/null +++ b/MCP/tools/orgs/orgs_update.go @@ -0,0 +1,125 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s", cfg.BaseURL, org) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org", + mcp.WithDescription("Update an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithBoolean("members_can_create_private_repositories", mcp.Description("Input parameter: Whether organization members can create private repositories, which are visible to organization members with permission. For more information, see \"[Restricting repository creation in your organization](https://docs.github.com/github/setting-up-and-managing-organizations-and-teams/restricting-repository-creation-in-your-organization)\" in the GitHub Help documentation.")), + mcp.WithString("email", mcp.Description("Input parameter: The publicly visible email address.")), + mcp.WithBoolean("members_can_fork_private_repositories", mcp.Description("Input parameter: Whether organization members can fork private organization repositories.")), + mcp.WithString("description", mcp.Description("Input parameter: The description of the company. The maximum size is 160 characters.")), + mcp.WithBoolean("members_can_create_public_repositories", mcp.Description("Input parameter: Whether organization members can create public repositories, which are visible to anyone. For more information, see \"[Restricting repository creation in your organization](https://docs.github.com/github/setting-up-and-managing-organizations-and-teams/restricting-repository-creation-in-your-organization)\" in the GitHub Help documentation.")), + mcp.WithString("members_allowed_repository_creation_type", mcp.Description("Input parameter: Specifies which types of repositories non-admin organization members can create. `private` is only available to repositories that are part of an organization on GitHub Enterprise Cloud. \n**Note:** This parameter is closing down and will be removed in the future. Its return value ignores internal repositories. Using this parameter overrides values set in `members_can_create_repositories`. See the parameter deprecation notice in the operation description for details.")), + mcp.WithBoolean("advanced_security_enabled_for_new_repositories", mcp.Description("Input parameter: **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead.\n\nWhether GitHub Advanced Security is automatically enabled for new repositories and repositories transferred to this organization.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nYou can check which security and analysis features are currently enabled by using a `GET /orgs/{org}` request.")), + mcp.WithBoolean("deploy_keys_enabled_for_repositories", mcp.Description("Input parameter: Controls whether or not deploy keys may be added and used for repositories in the organization.")), + mcp.WithBoolean("members_can_create_public_pages", mcp.Description("Input parameter: Whether organization members can create public GitHub Pages sites. Existing published sites will not be impacted.")), + mcp.WithString("company", mcp.Description("Input parameter: The company name.")), + mcp.WithString("default_repository_permission", mcp.Description("Input parameter: Default permission level members have for organization repositories.")), + mcp.WithBoolean("secret_scanning_push_protection_custom_link_enabled", mcp.Description("Input parameter: Whether a custom link is shown to contributors who are blocked from pushing a secret by push protection.")), + mcp.WithString("location", mcp.Description("Input parameter: The location.")), + mcp.WithString("secret_scanning_push_protection_custom_link", mcp.Description("Input parameter: If `secret_scanning_push_protection_custom_link_enabled` is true, the URL that will be displayed to contributors who are blocked from pushing a secret.")), + mcp.WithBoolean("has_organization_projects", mcp.Description("Input parameter: Whether an organization can use organization projects.")), + mcp.WithBoolean("members_can_create_private_pages", mcp.Description("Input parameter: Whether organization members can create private GitHub Pages sites. Existing published sites will not be impacted.")), + mcp.WithBoolean("members_can_create_repositories", mcp.Description("Input parameter: Whether of non-admin organization members can create repositories. **Note:** A parameter can override this parameter. See `members_allowed_repository_creation_type` in this table for details.")), + mcp.WithBoolean("dependency_graph_enabled_for_new_repositories", mcp.Description("Input parameter: **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead.\n\nWhether dependency graph is automatically enabled for new repositories and repositories transferred to this organization.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nYou can check which security and analysis features are currently enabled by using a `GET /orgs/{org}` request.")), + mcp.WithBoolean("has_repository_projects", mcp.Description("Input parameter: Whether repositories that belong to the organization can use repository projects.")), + mcp.WithString("blog", mcp.Description("")), + mcp.WithString("name", mcp.Description("Input parameter: The shorthand name of the company.")), + mcp.WithBoolean("secret_scanning_enabled_for_new_repositories", mcp.Description("Input parameter: **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead.\n\nWhether secret scanning is automatically enabled for new repositories and repositories transferred to this organization.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nYou can check which security and analysis features are currently enabled by using a `GET /orgs/{org}` request.")), + mcp.WithString("twitter_username", mcp.Description("Input parameter: The Twitter username of the company.")), + mcp.WithBoolean("secret_scanning_push_protection_enabled_for_new_repositories", mcp.Description("Input parameter: **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead.\n\nWhether secret scanning push protection is automatically enabled for new repositories and repositories transferred to this organization.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nYou can check which security and analysis features are currently enabled by using a `GET /orgs/{org}` request.")), + mcp.WithBoolean("members_can_create_pages", mcp.Description("Input parameter: Whether organization members can create GitHub Pages sites. Existing published sites will not be impacted.")), + mcp.WithBoolean("members_can_create_internal_repositories", mcp.Description("Input parameter: Whether organization members can create internal repositories, which are visible to all enterprise members. You can only allow members to create internal repositories if your organization is associated with an enterprise account using GitHub Enterprise Cloud or GitHub Enterprise Server 2.20+. For more information, see \"[Restricting repository creation in your organization](https://docs.github.com/github/setting-up-and-managing-organizations-and-teams/restricting-repository-creation-in-your-organization)\" in the GitHub Help documentation.")), + mcp.WithBoolean("web_commit_signoff_required", mcp.Description("Input parameter: Whether contributors to organization repositories are required to sign off on commits they make through GitHub's web interface.")), + mcp.WithString("billing_email", mcp.Description("Input parameter: Billing email address. This address is not publicized.")), + mcp.WithBoolean("dependabot_alerts_enabled_for_new_repositories", mcp.Description("Input parameter: **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead.\n\nWhether Dependabot alerts are automatically enabled for new repositories and repositories transferred to this organization.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nYou can check which security and analysis features are currently enabled by using a `GET /orgs/{org}` request.")), + mcp.WithBoolean("dependabot_security_updates_enabled_for_new_repositories", mcp.Description("Input parameter: **Endpoint closing down notice.** Please use [code security configurations](https://docs.github.com/rest/code-security/configurations) instead.\n\nWhether Dependabot security updates are automatically enabled for new repositories and repositories transferred to this organization.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nYou can check which security and analysis features are currently enabled by using a `GET /orgs/{org}` request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_updateHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update_issue_type.go b/MCP/tools/orgs/orgs_update_issue_type.go new file mode 100644 index 0000000..a252390 --- /dev/null +++ b/MCP/tools/orgs/orgs_update_issue_type.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_update_issue_typeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + issue_type_idVal, ok := args["issue_type_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_type_id"), nil + } + issue_type_id, ok := issue_type_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_type_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/issue-types/%s", cfg.BaseURL, org, issue_type_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_update_issue_typeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_issue-types_issue_type_id", + mcp.WithDescription("Update issue type for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("issue_type_id", mcp.Required(), mcp.Description("The unique identifier of the issue type.")), + mcp.WithString("color", mcp.Description("Input parameter: Color for the issue type.")), + mcp.WithString("description", mcp.Description("Input parameter: Description of the issue type.")), + mcp.WithBoolean("is_enabled", mcp.Required(), mcp.Description("Input parameter: Whether or not the issue type is enabled at the organization level.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the issue type.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_update_issue_typeHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update_membership_for_authenticated_user.go b/MCP/tools/orgs/orgs_update_membership_for_authenticated_user.go new file mode 100644 index 0000000..e20cc49 --- /dev/null +++ b/MCP/tools/orgs/orgs_update_membership_for_authenticated_user.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_update_membership_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/memberships/orgs/%s", cfg.BaseURL, org) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_update_membership_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_user_memberships_orgs_org", + mcp.WithDescription("Update an organization membership for the authenticated user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: The state that the membership should be in. Only `\"active\"` will be accepted.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_update_membership_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update_pat_access.go b/MCP/tools/orgs/orgs_update_pat_access.go new file mode 100644 index 0000000..eb60406 --- /dev/null +++ b/MCP/tools/orgs/orgs_update_pat_access.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_update_pat_accessHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + pat_idVal, ok := args["pat_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pat_id"), nil + } + pat_id, ok := pat_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pat_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-tokens/%s", cfg.BaseURL, org, pat_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_update_pat_accessTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_personal-access-tokens_pat_id", + mcp.WithDescription("Update the access a fine-grained personal access token has to organization resources"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("pat_id", mcp.Required(), mcp.Description("The unique identifier of the fine-grained personal access token.")), + mcp.WithString("action", mcp.Required(), mcp.Description("Input parameter: Action to apply to the fine-grained personal access token.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_update_pat_accessHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update_pat_accesses.go b/MCP/tools/orgs/orgs_update_pat_accesses.go new file mode 100644 index 0000000..b7fd2fd --- /dev/null +++ b/MCP/tools/orgs/orgs_update_pat_accesses.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_update_pat_accessesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/personal-access-tokens", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_update_pat_accessesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_personal-access-tokens", + mcp.WithDescription("Update the access to organization resources via fine-grained personal access tokens"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithArray("pat_ids", mcp.Required(), mcp.Description("Input parameter: The IDs of the fine-grained personal access tokens.")), + mcp.WithString("action", mcp.Required(), mcp.Description("Input parameter: Action to apply to the fine-grained personal access token.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_update_pat_accessesHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update_webhook.go b/MCP/tools/orgs/orgs_update_webhook.go new file mode 100644 index 0000000..85856d7 --- /dev/null +++ b/MCP/tools/orgs/orgs_update_webhook.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_update_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s", cfg.BaseURL, org, hook_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_update_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_hooks_hook_id", + mcp.WithDescription("Update an organization webhook"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithObject("config", mcp.Description("Input parameter: Key/value pairs to provide settings for this webhook.")), + mcp.WithArray("events", mcp.Description("Input parameter: Determines what [events](https://docs.github.com/webhooks/event-payloads) the hook is triggered for.")), + mcp.WithString("name", mcp.Description("")), + mcp.WithBoolean("active", mcp.Description("Input parameter: Determines if notifications are sent when the webhook is triggered. Set to `true` to send notifications.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_update_webhookHandler(cfg), + } +} diff --git a/MCP/tools/orgs/orgs_update_webhook_config_for_org.go b/MCP/tools/orgs/orgs_update_webhook_config_for_org.go new file mode 100644 index 0000000..aea6489 --- /dev/null +++ b/MCP/tools/orgs/orgs_update_webhook_config_for_org.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Orgs_update_webhook_config_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/hooks/%s/config", cfg.BaseURL, org, hook_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateOrgs_update_webhook_config_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_hooks_hook_id_config", + mcp.WithDescription("Update a webhook configuration for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithString("insecure_ssl", mcp.Description("")), + mcp.WithString("secret", mcp.Description("Input parameter: If provided, the `secret` will be used as the `key` to generate the HMAC hex digest value for [delivery signature headers](https://docs.github.com/webhooks/event-payloads/#delivery-headers).")), + mcp.WithString("url", mcp.Description("Input parameter: The URL to which the payloads will be delivered.")), + mcp.WithString("content_type", mcp.Description("Input parameter: The media type used to serialize the payloads. Supported values include `json` and `form`. The default is `form`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Orgs_update_webhook_config_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_delete_package_for_authenticated_user.go b/MCP/tools/packages/packages_delete_package_for_authenticated_user.go new file mode 100644 index 0000000..58c5fdb --- /dev/null +++ b/MCP/tools/packages/packages_delete_package_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_delete_package_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + url := fmt.Sprintf("%s/user/packages/%s/%s", cfg.BaseURL, package_type, package_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_delete_package_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_packages_package_type_package_name", + mcp.WithDescription("Delete a package for the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_delete_package_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_delete_package_for_org.go b/MCP/tools/packages/packages_delete_package_for_org.go new file mode 100644 index 0000000..e036e78 --- /dev/null +++ b/MCP/tools/packages/packages_delete_package_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_delete_package_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s", cfg.BaseURL, package_type, package_name, org) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_delete_package_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_packages_package_type_package_name", + mcp.WithDescription("Delete a package for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_delete_package_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_delete_package_for_user.go b/MCP/tools/packages/packages_delete_package_for_user.go new file mode 100644 index 0000000..71c9c69 --- /dev/null +++ b/MCP/tools/packages/packages_delete_package_for_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_delete_package_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s", cfg.BaseURL, package_type, package_name, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_delete_package_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_users_username_packages_package_type_package_name", + mcp.WithDescription("Delete a package for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_delete_package_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_delete_package_version_for_authenticated_user.go b/MCP/tools/packages/packages_delete_package_version_for_authenticated_user.go new file mode 100644 index 0000000..59947fd --- /dev/null +++ b/MCP/tools/packages/packages_delete_package_version_for_authenticated_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_delete_package_version_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/user/packages/%s/%s/versions/%s", cfg.BaseURL, package_type, package_name, package_version_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_delete_package_version_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_packages_package_type_package_name_versions_package_version_id", + mcp.WithDescription("Delete a package version for the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_delete_package_version_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_delete_package_version_for_org.go b/MCP/tools/packages/packages_delete_package_version_for_org.go new file mode 100644 index 0000000..0def074 --- /dev/null +++ b/MCP/tools/packages/packages_delete_package_version_for_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_delete_package_version_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s/versions/%s", cfg.BaseURL, package_type, package_name, org, package_version_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_delete_package_version_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_packages_package_type_package_name_versions_package_version_id", + mcp.WithDescription("Delete package version for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_delete_package_version_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_delete_package_version_for_user.go b/MCP/tools/packages/packages_delete_package_version_for_user.go new file mode 100644 index 0000000..8c8c03d --- /dev/null +++ b/MCP/tools/packages/packages_delete_package_version_for_user.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_delete_package_version_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s/versions/%s", cfg.BaseURL, package_type, package_name, username, package_version_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_delete_package_version_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_users_username_packages_package_type_package_name_versions_package_version_id", + mcp.WithDescription("Delete package version for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_delete_package_version_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_authenticated_user.go b/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_authenticated_user.go new file mode 100644 index 0000000..81336f5 --- /dev/null +++ b/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_authenticated_user.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_all_package_versions_for_package_owned_by_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/packages/%s/%s/versions%s", cfg.BaseURL, package_type, package_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_all_package_versions_for_package_owned_by_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_packages_package_type_package_name_versions", + mcp.WithDescription("List package versions for a package owned by the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("state", mcp.Description("The state of the package, either active or deleted.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_all_package_versions_for_package_owned_by_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_org.go b/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_org.go new file mode 100644 index 0000000..5a28a20 --- /dev/null +++ b/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_org.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_all_package_versions_for_package_owned_by_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s/versions%s", cfg.BaseURL, package_type, package_name, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_all_package_versions_for_package_owned_by_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_packages_package_type_package_name_versions", + mcp.WithDescription("List package versions for a package owned by an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("state", mcp.Description("The state of the package, either active or deleted.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_all_package_versions_for_package_owned_by_orgHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_user.go b/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_user.go new file mode 100644 index 0000000..c30cbb0 --- /dev/null +++ b/MCP/tools/packages/packages_get_all_package_versions_for_package_owned_by_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_all_package_versions_for_package_owned_by_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s/versions", cfg.BaseURL, package_type, package_name, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_all_package_versions_for_package_owned_by_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_packages_package_type_package_name_versions", + mcp.WithDescription("List package versions for a package owned by a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_all_package_versions_for_package_owned_by_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_package_for_authenticated_user.go b/MCP/tools/packages/packages_get_package_for_authenticated_user.go new file mode 100644 index 0000000..15df687 --- /dev/null +++ b/MCP/tools/packages/packages_get_package_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_package_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + url := fmt.Sprintf("%s/user/packages/%s/%s", cfg.BaseURL, package_type, package_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_package_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_packages_package_type_package_name", + mcp.WithDescription("Get a package for the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_package_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_package_for_organization.go b/MCP/tools/packages/packages_get_package_for_organization.go new file mode 100644 index 0000000..5c2be37 --- /dev/null +++ b/MCP/tools/packages/packages_get_package_for_organization.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_package_for_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s", cfg.BaseURL, package_type, package_name, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_package_for_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_packages_package_type_package_name", + mcp.WithDescription("Get a package for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_package_for_organizationHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_package_for_user.go b/MCP/tools/packages/packages_get_package_for_user.go new file mode 100644 index 0000000..d45abbb --- /dev/null +++ b/MCP/tools/packages/packages_get_package_for_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_package_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s", cfg.BaseURL, package_type, package_name, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_package_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_packages_package_type_package_name", + mcp.WithDescription("Get a package for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_package_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_package_version_for_authenticated_user.go b/MCP/tools/packages/packages_get_package_version_for_authenticated_user.go new file mode 100644 index 0000000..d58441b --- /dev/null +++ b/MCP/tools/packages/packages_get_package_version_for_authenticated_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_package_version_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/user/packages/%s/%s/versions/%s", cfg.BaseURL, package_type, package_name, package_version_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_package_version_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_packages_package_type_package_name_versions_package_version_id", + mcp.WithDescription("Get a package version for the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_package_version_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_package_version_for_organization.go b/MCP/tools/packages/packages_get_package_version_for_organization.go new file mode 100644 index 0000000..0f4bd4d --- /dev/null +++ b/MCP/tools/packages/packages_get_package_version_for_organization.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_package_version_for_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s/versions/%s", cfg.BaseURL, package_type, package_name, org, package_version_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_package_version_for_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_packages_package_type_package_name_versions_package_version_id", + mcp.WithDescription("Get a package version for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_package_version_for_organizationHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_get_package_version_for_user.go b/MCP/tools/packages/packages_get_package_version_for_user.go new file mode 100644 index 0000000..5a7d45c --- /dev/null +++ b/MCP/tools/packages/packages_get_package_version_for_user.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_get_package_version_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s/versions/%s", cfg.BaseURL, package_type, package_name, package_version_id, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_get_package_version_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_packages_package_type_package_name_versions_package_version_id", + mcp.WithDescription("Get a package version for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_get_package_version_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_authenticated_user.go b/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_authenticated_user.go new file mode 100644 index 0000000..5d23783 --- /dev/null +++ b/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_authenticated_user.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_list_docker_migration_conflicting_packages_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/user/docker/conflicts", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_list_docker_migration_conflicting_packages_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_docker_conflicts", + mcp.WithDescription("Get list of conflicting packages during Docker migration for authenticated-user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_list_docker_migration_conflicting_packages_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_organization.go b/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_organization.go new file mode 100644 index 0000000..bbadf07 --- /dev/null +++ b/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_organization.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_list_docker_migration_conflicting_packages_for_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/docker/conflicts", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_list_docker_migration_conflicting_packages_for_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_docker_conflicts", + mcp.WithDescription("Get list of conflicting packages during Docker migration for organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_list_docker_migration_conflicting_packages_for_organizationHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_user.go b/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_user.go new file mode 100644 index 0000000..52e5b97 --- /dev/null +++ b/MCP/tools/packages/packages_list_docker_migration_conflicting_packages_for_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_list_docker_migration_conflicting_packages_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s/docker/conflicts", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_list_docker_migration_conflicting_packages_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_docker_conflicts", + mcp.WithDescription("Get list of conflicting packages during Docker migration for user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_list_docker_migration_conflicting_packages_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_list_packages_for_authenticated_user.go b/MCP/tools/packages/packages_list_packages_for_authenticated_user.go new file mode 100644 index 0000000..af2ed76 --- /dev/null +++ b/MCP/tools/packages/packages_list_packages_for_authenticated_user.go @@ -0,0 +1,90 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_list_packages_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["package_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("package_type=%v", val)) + } + if val, ok := args["visibility"]; ok { + queryParams = append(queryParams, fmt.Sprintf("visibility=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/packages%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_list_packages_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_packages", + mcp.WithDescription("List packages for the authenticated user's namespace"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("visibility", mcp.Description("The selected visibility of the packages. This parameter is optional and only filters an existing result set.\n\nThe `internal` visibility is only supported for GitHub Packages registries that allow for granular permissions. For other ecosystems `internal` is synonymous with `private`.\nFor the list of GitHub Packages registries that support granular permissions, see \"[About permissions for GitHub Packages](https://docs.github.com/packages/learn-github-packages/about-permissions-for-github-packages#granular-permissions-for-userorganization-scoped-packages).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_list_packages_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_list_packages_for_organization.go b/MCP/tools/packages/packages_list_packages_for_organization.go new file mode 100644 index 0000000..26716de --- /dev/null +++ b/MCP/tools/packages/packages_list_packages_for_organization.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_list_packages_for_organizationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["package_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("package_type=%v", val)) + } + if val, ok := args["visibility"]; ok { + queryParams = append(queryParams, fmt.Sprintf("visibility=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/packages%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_list_packages_for_organizationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_packages", + mcp.WithDescription("List packages for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("visibility", mcp.Description("The selected visibility of the packages. This parameter is optional and only filters an existing result set.\n\nThe `internal` visibility is only supported for GitHub Packages registries that allow for granular permissions. For other ecosystems `internal` is synonymous with `private`.\nFor the list of GitHub Packages registries that support granular permissions, see \"[About permissions for GitHub Packages](https://docs.github.com/packages/learn-github-packages/about-permissions-for-github-packages#granular-permissions-for-userorganization-scoped-packages).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_list_packages_for_organizationHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_list_packages_for_user.go b/MCP/tools/packages/packages_list_packages_for_user.go new file mode 100644 index 0000000..13f5e8a --- /dev/null +++ b/MCP/tools/packages/packages_list_packages_for_user.go @@ -0,0 +1,99 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_list_packages_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["package_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("package_type=%v", val)) + } + if val, ok := args["visibility"]; ok { + queryParams = append(queryParams, fmt.Sprintf("visibility=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/packages%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Package + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_list_packages_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_packages", + mcp.WithDescription("List packages for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("visibility", mcp.Description("The selected visibility of the packages. This parameter is optional and only filters an existing result set.\n\nThe `internal` visibility is only supported for GitHub Packages registries that allow for granular permissions. For other ecosystems `internal` is synonymous with `private`.\nFor the list of GitHub Packages registries that support granular permissions, see \"[About permissions for GitHub Packages](https://docs.github.com/packages/learn-github-packages/about-permissions-for-github-packages#granular-permissions-for-userorganization-scoped-packages).\"")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_list_packages_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_restore_package_for_authenticated_user.go b/MCP/tools/packages/packages_restore_package_for_authenticated_user.go new file mode 100644 index 0000000..f990946 --- /dev/null +++ b/MCP/tools/packages/packages_restore_package_for_authenticated_user.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_restore_package_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["token"]; ok { + queryParams = append(queryParams, fmt.Sprintf("token=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/packages/%s/%s/restore%s", cfg.BaseURL, package_type, package_name, queryString) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_restore_package_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_packages_package_type_package_name_restore", + mcp.WithDescription("Restore a package for the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("token", mcp.Description("package token")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_restore_package_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_restore_package_for_org.go b/MCP/tools/packages/packages_restore_package_for_org.go new file mode 100644 index 0000000..6553660 --- /dev/null +++ b/MCP/tools/packages/packages_restore_package_for_org.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_restore_package_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["token"]; ok { + queryParams = append(queryParams, fmt.Sprintf("token=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s/restore%s", cfg.BaseURL, package_type, package_name, org, queryString) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_restore_package_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_packages_package_type_package_name_restore", + mcp.WithDescription("Restore a package for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("token", mcp.Description("package token")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_restore_package_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_restore_package_for_user.go b/MCP/tools/packages/packages_restore_package_for_user.go new file mode 100644 index 0000000..14901d9 --- /dev/null +++ b/MCP/tools/packages/packages_restore_package_for_user.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_restore_package_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["token"]; ok { + queryParams = append(queryParams, fmt.Sprintf("token=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s/restore%s", cfg.BaseURL, package_type, package_name, username, queryString) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_restore_package_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_users_username_packages_package_type_package_name_restore", + mcp.WithDescription("Restore a package for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("token", mcp.Description("package token")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_restore_package_for_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_restore_package_version_for_authenticated_user.go b/MCP/tools/packages/packages_restore_package_version_for_authenticated_user.go new file mode 100644 index 0000000..2de17e6 --- /dev/null +++ b/MCP/tools/packages/packages_restore_package_version_for_authenticated_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_restore_package_version_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/user/packages/%s/%s/versions/%s/restore", cfg.BaseURL, package_type, package_name, package_version_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_restore_package_version_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_packages_package_type_package_name_versions_package_version_id_restore", + mcp.WithDescription("Restore a package version for the authenticated user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_restore_package_version_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_restore_package_version_for_org.go b/MCP/tools/packages/packages_restore_package_version_for_org.go new file mode 100644 index 0000000..af218d2 --- /dev/null +++ b/MCP/tools/packages/packages_restore_package_version_for_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_restore_package_version_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/packages/%s/%s/versions/%s/restore", cfg.BaseURL, package_type, package_name, org, package_version_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_restore_package_version_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_packages_package_type_package_name_versions_package_version_id_restore", + mcp.WithDescription("Restore package version for an organization"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_restore_package_version_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/packages/packages_restore_package_version_for_user.go b/MCP/tools/packages/packages_restore_package_version_for_user.go new file mode 100644 index 0000000..f3e4851 --- /dev/null +++ b/MCP/tools/packages/packages_restore_package_version_for_user.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Packages_restore_package_version_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + package_typeVal, ok := args["package_type"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_type"), nil + } + package_type, ok := package_typeVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_type"), nil + } + package_nameVal, ok := args["package_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_name"), nil + } + package_name, ok := package_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_name"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + package_version_idVal, ok := args["package_version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: package_version_id"), nil + } + package_version_id, ok := package_version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: package_version_id"), nil + } + url := fmt.Sprintf("%s/users/%s/packages/%s/%s/versions/%s/restore", cfg.BaseURL, package_type, package_name, username, package_version_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePackages_restore_package_version_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_users_username_packages_package_type_package_name_versions_package_version_id_restore", + mcp.WithDescription("Restore package version for a user"), + mcp.WithString("package_type", mcp.Required(), mcp.Description("The type of supported package. Packages in GitHub's Gradle registry have the type `maven`. Docker images pushed to GitHub's Container registry (`ghcr.io`) have the type `container`. You can use the type `docker` to find images that were pushed to GitHub's Docker registry (`docker.pkg.github.com`), even if these have now been migrated to the Container registry.")), + mcp.WithString("package_name", mcp.Required(), mcp.Description("The name of the package.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("package_version_id", mcp.Required(), mcp.Description("Unique identifier of the package version.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Packages_restore_package_version_for_userHandler(cfg), + } +} diff --git a/MCP/tools/private_registries/private_registries_create_org_private_registry.go b/MCP/tools/private_registries/private_registries_create_org_private_registry.go new file mode 100644 index 0000000..9fa1bcd --- /dev/null +++ b/MCP/tools/private_registries/private_registries_create_org_private_registry.go @@ -0,0 +1,102 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Private_registries_create_org_private_registryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/private-registries", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePrivate_registries_create_org_private_registryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_private-registries", + mcp.WithDescription("Create a private registry for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("url", mcp.Required(), mcp.Description("Input parameter: The URL of the private registry.")), + mcp.WithString("username", mcp.Description("Input parameter: The username to use when authenticating with the private registry. This field should be omitted if the private registry does not require a username for authentication.")), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: Which type of organization repositories have access to the private registry. `selected` means only the repositories specified by `selected_repository_ids` can access the private registry.")), + mcp.WithString("encrypted_value", mcp.Required(), mcp.Description("Input parameter: The value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get private registries public key for an organization](https://docs.github.com/rest/private-registries/organization-configurations#get-private-registries-public-key-for-an-organization) endpoint.")), + mcp.WithString("key_id", mcp.Required(), mcp.Description("Input parameter: The ID of the key you used to encrypt the secret.")), + mcp.WithString("registry_type", mcp.Required(), mcp.Description("Input parameter: The registry type.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository IDs that can access the organization private registry. You can only provide a list of repository IDs when `visibility` is set to `selected`. You can manage the list of selected repositories using the [Update a private registry for an organization](https://docs.github.com/rest/private-registries/organization-configurations#update-a-private-registry-for-an-organization) endpoint. This field should be omitted if `visibility` is set to `all` or `private`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Private_registries_create_org_private_registryHandler(cfg), + } +} diff --git a/MCP/tools/private_registries/private_registries_delete_org_private_registry.go b/MCP/tools/private_registries/private_registries_delete_org_private_registry.go new file mode 100644 index 0000000..cc69c1a --- /dev/null +++ b/MCP/tools/private_registries/private_registries_delete_org_private_registry.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Private_registries_delete_org_private_registryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/private-registries/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePrivate_registries_delete_org_private_registryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_private-registries_secret_name", + mcp.WithDescription("Delete a private registry for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Private_registries_delete_org_private_registryHandler(cfg), + } +} diff --git a/MCP/tools/private_registries/private_registries_get_org_private_registry.go b/MCP/tools/private_registries/private_registries_get_org_private_registry.go new file mode 100644 index 0000000..e3547e1 --- /dev/null +++ b/MCP/tools/private_registries/private_registries_get_org_private_registry.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Private_registries_get_org_private_registryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + url := fmt.Sprintf("%s/orgs/%s/private-registries/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePrivate_registries_get_org_private_registryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_private-registries_secret_name", + mcp.WithDescription("Get a private registry for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Private_registries_get_org_private_registryHandler(cfg), + } +} diff --git a/MCP/tools/private_registries/private_registries_get_org_public_key.go b/MCP/tools/private_registries/private_registries_get_org_public_key.go new file mode 100644 index 0000000..dda1a1b --- /dev/null +++ b/MCP/tools/private_registries/private_registries_get_org_public_key.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Private_registries_get_org_public_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + url := fmt.Sprintf("%s/orgs/%s/private-registries/public-key", cfg.BaseURL, org) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePrivate_registries_get_org_public_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_private-registries_public-key", + mcp.WithDescription("Get private registries public key for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Private_registries_get_org_public_keyHandler(cfg), + } +} diff --git a/MCP/tools/private_registries/private_registries_list_org_private_registries.go b/MCP/tools/private_registries/private_registries_list_org_private_registries.go new file mode 100644 index 0000000..e0172df --- /dev/null +++ b/MCP/tools/private_registries/private_registries_list_org_private_registries.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Private_registries_list_org_private_registriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/private-registries%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePrivate_registries_list_org_private_registriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_private-registries", + mcp.WithDescription("List private registries for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Private_registries_list_org_private_registriesHandler(cfg), + } +} diff --git a/MCP/tools/private_registries/private_registries_update_org_private_registry.go b/MCP/tools/private_registries/private_registries_update_org_private_registry.go new file mode 100644 index 0000000..9ca2c17 --- /dev/null +++ b/MCP/tools/private_registries/private_registries_update_org_private_registry.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Private_registries_update_org_private_registryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + secret_nameVal, ok := args["secret_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: secret_name"), nil + } + secret_name, ok := secret_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: secret_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/private-registries/%s", cfg.BaseURL, org, secret_name) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePrivate_registries_update_org_private_registryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_private-registries_secret_name", + mcp.WithDescription("Update a private registry for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("secret_name", mcp.Required(), mcp.Description("The name of the secret.")), + mcp.WithString("url", mcp.Description("Input parameter: The URL of the private registry.")), + mcp.WithString("username", mcp.Description("Input parameter: The username to use when authenticating with the private registry. This field should be omitted if the private registry does not require a username for authentication.")), + mcp.WithString("visibility", mcp.Description("Input parameter: Which type of organization repositories have access to the private registry. `selected` means only the repositories specified by `selected_repository_ids` can access the private registry.")), + mcp.WithString("encrypted_value", mcp.Description("Input parameter: The value for your secret, encrypted with [LibSodium](https://libsodium.gitbook.io/doc/bindings_for_other_languages) using the public key retrieved from the [Get private registries public key for an organization](https://docs.github.com/rest/private-registries/organization-configurations#get-private-registries-public-key-for-an-organization) endpoint.")), + mcp.WithString("key_id", mcp.Description("Input parameter: The ID of the key you used to encrypt the secret.")), + mcp.WithString("registry_type", mcp.Description("Input parameter: The registry type.")), + mcp.WithArray("selected_repository_ids", mcp.Description("Input parameter: An array of repository IDs that can access the organization private registry. You can only provide a list of repository IDs when `visibility` is set to `selected`. This field should be omitted if `visibility` is set to `all` or `private`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Private_registries_update_org_private_registryHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_add_collaborator.go b/MCP/tools/projects/projects_add_collaborator.go new file mode 100644 index 0000000..2fac21c --- /dev/null +++ b/MCP/tools/projects/projects_add_collaborator.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_add_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/%s/collaborators/%s", cfg.BaseURL, project_id, username) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_add_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_projects_project_id_collaborators_username", + mcp.WithDescription("Add project collaborator"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("permission", mcp.Description("Input parameter: The permission to grant the collaborator.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_add_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_create_card.go b/MCP/tools/projects/projects_create_card.go new file mode 100644 index 0000000..9d83b80 --- /dev/null +++ b/MCP/tools/projects/projects_create_card.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_create_cardHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + column_idVal, ok := args["column_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: column_id"), nil + } + column_id, ok := column_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: column_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/columns/%s/cards", cfg.BaseURL, column_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_create_cardTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_projects_columns_column_id_cards", + mcp.WithDescription("Create a project card"), + mcp.WithNumber("column_id", mcp.Required(), mcp.Description("The unique identifier of the column.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_create_cardHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_create_column.go b/MCP/tools/projects/projects_create_column.go new file mode 100644 index 0000000..a6ddb2d --- /dev/null +++ b/MCP/tools/projects/projects_create_column.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_create_columnHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/%s/columns", cfg.BaseURL, project_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_create_columnTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_projects_project_id_columns", + mcp.WithDescription("Create a project column"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the project column")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_create_columnHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_create_for_authenticated_user.go b/MCP/tools/projects/projects_create_for_authenticated_user.go new file mode 100644 index 0000000..099e3d1 --- /dev/null +++ b/MCP/tools/projects/projects_create_for_authenticated_user.go @@ -0,0 +1,88 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_create_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/projects", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_create_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_projects", + mcp.WithDescription("Create a user project"), + mcp.WithString("body", mcp.Description("Input parameter: Body of the project")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the project")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_create_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_create_for_org.go b/MCP/tools/projects/projects_create_for_org.go new file mode 100644 index 0000000..18707db --- /dev/null +++ b/MCP/tools/projects/projects_create_for_org.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_create_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/projects", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_create_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_projects", + mcp.WithDescription("Create an organization project"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("body", mcp.Description("Input parameter: The description of the project.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_create_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_create_for_repo.go b/MCP/tools/projects/projects_create_for_repo.go new file mode 100644 index 0000000..4908ff0 --- /dev/null +++ b/MCP/tools/projects/projects_create_for_repo.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_create_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/projects", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_create_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_projects", + mcp.WithDescription("Create a repository project"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("body", mcp.Description("Input parameter: The description of the project.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_create_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_delete.go b/MCP/tools/projects/projects_delete.go new file mode 100644 index 0000000..bcd99ef --- /dev/null +++ b/MCP/tools/projects/projects_delete.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_deleteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + url := fmt.Sprintf("%s/projects/%s", cfg.BaseURL, project_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_deleteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_projects_project_id", + mcp.WithDescription("Delete a project"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_deleteHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_delete_card.go b/MCP/tools/projects/projects_delete_card.go new file mode 100644 index 0000000..7772d96 --- /dev/null +++ b/MCP/tools/projects/projects_delete_card.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_delete_cardHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + card_idVal, ok := args["card_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: card_id"), nil + } + card_id, ok := card_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: card_id"), nil + } + url := fmt.Sprintf("%s/projects/columns/cards/%s", cfg.BaseURL, card_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_delete_cardTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_projects_columns_cards_card_id", + mcp.WithDescription("Delete a project card"), + mcp.WithNumber("card_id", mcp.Required(), mcp.Description("The unique identifier of the card.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_delete_cardHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_delete_column.go b/MCP/tools/projects/projects_delete_column.go new file mode 100644 index 0000000..b6ff113 --- /dev/null +++ b/MCP/tools/projects/projects_delete_column.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_delete_columnHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + column_idVal, ok := args["column_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: column_id"), nil + } + column_id, ok := column_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: column_id"), nil + } + url := fmt.Sprintf("%s/projects/columns/%s", cfg.BaseURL, column_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_delete_columnTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_projects_columns_column_id", + mcp.WithDescription("Delete a project column"), + mcp.WithNumber("column_id", mcp.Required(), mcp.Description("The unique identifier of the column.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_delete_columnHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_get.go b/MCP/tools/projects/projects_get.go new file mode 100644 index 0000000..6d4b55a --- /dev/null +++ b/MCP/tools/projects/projects_get.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + url := fmt.Sprintf("%s/projects/%s", cfg.BaseURL, project_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_project_id", + mcp.WithDescription("Get a project"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_getHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_get_card.go b/MCP/tools/projects/projects_get_card.go new file mode 100644 index 0000000..1222253 --- /dev/null +++ b/MCP/tools/projects/projects_get_card.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_get_cardHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + card_idVal, ok := args["card_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: card_id"), nil + } + card_id, ok := card_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: card_id"), nil + } + url := fmt.Sprintf("%s/projects/columns/cards/%s", cfg.BaseURL, card_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_get_cardTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_columns_cards_card_id", + mcp.WithDescription("Get a project card"), + mcp.WithNumber("card_id", mcp.Required(), mcp.Description("The unique identifier of the card.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_get_cardHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_get_column.go b/MCP/tools/projects/projects_get_column.go new file mode 100644 index 0000000..e950bec --- /dev/null +++ b/MCP/tools/projects/projects_get_column.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_get_columnHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + column_idVal, ok := args["column_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: column_id"), nil + } + column_id, ok := column_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: column_id"), nil + } + url := fmt.Sprintf("%s/projects/columns/%s", cfg.BaseURL, column_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_get_columnTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_columns_column_id", + mcp.WithDescription("Get a project column"), + mcp.WithNumber("column_id", mcp.Required(), mcp.Description("The unique identifier of the column.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_get_columnHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_get_permission_for_user.go b/MCP/tools/projects/projects_get_permission_for_user.go new file mode 100644 index 0000000..823510d --- /dev/null +++ b/MCP/tools/projects/projects_get_permission_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_get_permission_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/projects/%s/collaborators/%s/permission", cfg.BaseURL, project_id, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_get_permission_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_project_id_collaborators_username_permission", + mcp.WithDescription("Get project permission for a user"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_get_permission_for_userHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_list_cards.go b/MCP/tools/projects/projects_list_cards.go new file mode 100644 index 0000000..42ee2ec --- /dev/null +++ b/MCP/tools/projects/projects_list_cards.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_list_cardsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + column_idVal, ok := args["column_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: column_id"), nil + } + column_id, ok := column_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: column_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["archived_state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("archived_state=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/projects/columns/%s/cards%s", cfg.BaseURL, column_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_list_cardsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_columns_column_id_cards", + mcp.WithDescription("List project cards"), + mcp.WithNumber("column_id", mcp.Required(), mcp.Description("The unique identifier of the column.")), + mcp.WithString("archived_state", mcp.Description("Filters the project cards that are returned by the card's state.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_list_cardsHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_list_collaborators.go b/MCP/tools/projects/projects_list_collaborators.go new file mode 100644 index 0000000..ce66018 --- /dev/null +++ b/MCP/tools/projects/projects_list_collaborators.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_list_collaboratorsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["affiliation"]; ok { + queryParams = append(queryParams, fmt.Sprintf("affiliation=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/projects/%s/collaborators%s", cfg.BaseURL, project_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_list_collaboratorsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_project_id_collaborators", + mcp.WithDescription("List project collaborators"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("affiliation", mcp.Description("Filters the collaborators by their affiliation. `outside` means outside collaborators of a project that are not a member of the project's organization. `direct` means collaborators with permissions to a project, regardless of organization membership status. `all` means all collaborators the authenticated user can see.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_list_collaboratorsHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_list_columns.go b/MCP/tools/projects/projects_list_columns.go new file mode 100644 index 0000000..6aa5f94 --- /dev/null +++ b/MCP/tools/projects/projects_list_columns.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_list_columnsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/projects/%s/columns%s", cfg.BaseURL, project_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_list_columnsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_projects_project_id_columns", + mcp.WithDescription("List project columns"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_list_columnsHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_list_for_org.go b/MCP/tools/projects/projects_list_for_org.go new file mode 100644 index 0000000..ec18753 --- /dev/null +++ b/MCP/tools/projects/projects_list_for_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_list_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/projects%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_list_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_projects", + mcp.WithDescription("List organization projects"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("Indicates the state of the projects to return.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_list_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_list_for_repo.go b/MCP/tools/projects/projects_list_for_repo.go new file mode 100644 index 0000000..84b7069 --- /dev/null +++ b/MCP/tools/projects/projects_list_for_repo.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_list_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/projects%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_list_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_projects", + mcp.WithDescription("List repository projects"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("Indicates the state of the projects to return.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_list_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_list_for_user.go b/MCP/tools/projects/projects_list_for_user.go new file mode 100644 index 0000000..56b7ff0 --- /dev/null +++ b/MCP/tools/projects/projects_list_for_user.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_list_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/projects%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_list_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_projects", + mcp.WithDescription("List user projects"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("state", mcp.Description("Indicates the state of the projects to return.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_list_for_userHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_move_card.go b/MCP/tools/projects/projects_move_card.go new file mode 100644 index 0000000..6e1853d --- /dev/null +++ b/MCP/tools/projects/projects_move_card.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_move_cardHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + card_idVal, ok := args["card_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: card_id"), nil + } + card_id, ok := card_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: card_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/columns/cards/%s/moves", cfg.BaseURL, card_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_move_cardTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_projects_columns_cards_card_id_moves", + mcp.WithDescription("Move a project card"), + mcp.WithNumber("card_id", mcp.Required(), mcp.Description("The unique identifier of the card.")), + mcp.WithString("position", mcp.Required(), mcp.Description("Input parameter: The position of the card in a column. Can be one of: `top`, `bottom`, or `after:` to place after the specified card.")), + mcp.WithNumber("column_id", mcp.Description("Input parameter: The unique identifier of the column the card should be moved to")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_move_cardHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_move_column.go b/MCP/tools/projects/projects_move_column.go new file mode 100644 index 0000000..164c546 --- /dev/null +++ b/MCP/tools/projects/projects_move_column.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_move_columnHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + column_idVal, ok := args["column_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: column_id"), nil + } + column_id, ok := column_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: column_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/columns/%s/moves", cfg.BaseURL, column_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_move_columnTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_projects_columns_column_id_moves", + mcp.WithDescription("Move a project column"), + mcp.WithNumber("column_id", mcp.Required(), mcp.Description("The unique identifier of the column.")), + mcp.WithString("position", mcp.Required(), mcp.Description("Input parameter: The position of the column in a project. Can be one of: `first`, `last`, or `after:` to place after the specified column.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_move_columnHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_remove_collaborator.go b/MCP/tools/projects/projects_remove_collaborator.go new file mode 100644 index 0000000..9c018e4 --- /dev/null +++ b/MCP/tools/projects/projects_remove_collaborator.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_remove_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/projects/%s/collaborators/%s", cfg.BaseURL, project_id, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_remove_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_projects_project_id_collaborators_username", + mcp.WithDescription("Remove user as a collaborator"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_remove_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_update.go b/MCP/tools/projects/projects_update.go new file mode 100644 index 0000000..4f7e62b --- /dev/null +++ b/MCP/tools/projects/projects_update.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/%s", cfg.BaseURL, project_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Project + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_projects_project_id", + mcp.WithDescription("Update a project"), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("name", mcp.Description("Input parameter: Name of the project")), + mcp.WithString("organization_permission", mcp.Description("Input parameter: The baseline permission that all organization members have on this project")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Whether or not this project can be seen by everyone.")), + mcp.WithString("state", mcp.Description("Input parameter: State of the project; either 'open' or 'closed'")), + mcp.WithString("body", mcp.Description("Input parameter: Body of the project")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_updateHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_update_card.go b/MCP/tools/projects/projects_update_card.go new file mode 100644 index 0000000..dbdad3e --- /dev/null +++ b/MCP/tools/projects/projects_update_card.go @@ -0,0 +1,97 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_update_cardHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + card_idVal, ok := args["card_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: card_id"), nil + } + card_id, ok := card_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: card_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/columns/cards/%s", cfg.BaseURL, card_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_update_cardTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_projects_columns_cards_card_id", + mcp.WithDescription("Update an existing project card"), + mcp.WithNumber("card_id", mcp.Required(), mcp.Description("The unique identifier of the card.")), + mcp.WithBoolean("archived", mcp.Description("Input parameter: Whether or not the card is archived")), + mcp.WithString("note", mcp.Description("Input parameter: The project card's note")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_update_cardHandler(cfg), + } +} diff --git a/MCP/tools/projects/projects_update_column.go b/MCP/tools/projects/projects_update_column.go new file mode 100644 index 0000000..deda8be --- /dev/null +++ b/MCP/tools/projects/projects_update_column.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Projects_update_columnHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + column_idVal, ok := args["column_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: column_id"), nil + } + column_id, ok := column_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: column_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/projects/columns/%s", cfg.BaseURL, column_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateProjects_update_columnTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_projects_columns_column_id", + mcp.WithDescription("Update an existing project column"), + mcp.WithNumber("column_id", mcp.Required(), mcp.Description("The unique identifier of the column.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: Name of the project column")), + ) + + return models.Tool{ + Definition: tool, + Handler: Projects_update_columnHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_check_if_merged.go b/MCP/tools/pulls/pulls_check_if_merged.go new file mode 100644 index 0000000..6c10fd1 --- /dev/null +++ b/MCP/tools/pulls/pulls_check_if_merged.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_check_if_mergedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/merge", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_check_if_mergedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_merge", + mcp.WithDescription("Check if a pull request has been merged"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_check_if_mergedHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_create.go b/MCP/tools/pulls/pulls_create.go new file mode 100644 index 0000000..eb587f1 --- /dev/null +++ b/MCP/tools/pulls/pulls_create.go @@ -0,0 +1,112 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_createHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_createTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls", + mcp.WithDescription("Create a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("draft", mcp.Description("Input parameter: Indicates whether the pull request is a draft. See \"[Draft Pull Requests](https://docs.github.com/articles/about-pull-requests#draft-pull-requests)\" in the GitHub Help documentation to learn more.")), + mcp.WithString("head", mcp.Required(), mcp.Description("Input parameter: The name of the branch where your changes are implemented. For cross-repository pull requests in the same network, namespace `head` with a user like this: `username:branch`.")), + mcp.WithString("head_repo", mcp.Description("Input parameter: The name of the repository where the changes in the pull request were made. This field is required for cross-repository pull requests if both repositories are owned by the same organization.")), + mcp.WithNumber("issue", mcp.Description("Input parameter: An issue in the repository to convert to a pull request. The issue title, body, and comments will become the title, body, and comments on the new pull request. Required unless `title` is specified.")), + mcp.WithBoolean("maintainer_can_modify", mcp.Description("Input parameter: Indicates whether [maintainers can modify](https://docs.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/) the pull request.")), + mcp.WithString("title", mcp.Description("Input parameter: The title of the new pull request. Required unless `issue` is specified.")), + mcp.WithString("base", mcp.Required(), mcp.Description("Input parameter: The name of the branch you want the changes pulled into. This should be an existing branch on the current repository. You cannot submit a pull request to one repository that requests a merge to a base of another repository.")), + mcp.WithString("body", mcp.Description("Input parameter: The contents of the pull request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_createHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_create_reply_for_review_comment.go b/MCP/tools/pulls/pulls_create_reply_for_review_comment.go new file mode 100644 index 0000000..cbb696b --- /dev/null +++ b/MCP/tools/pulls/pulls_create_reply_for_review_comment.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_create_reply_for_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/comments/%s/replies", cfg.BaseURL, owner, repo, pull_number, comment_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_create_reply_for_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_pull_number_comments_comment_id_replies", + mcp.WithDescription("Create a reply for a review comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The text of the review comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_create_reply_for_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_create_review.go b/MCP/tools/pulls/pulls_create_review.go new file mode 100644 index 0000000..7b8cb43 --- /dev/null +++ b/MCP/tools/pulls/pulls_create_review.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_create_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_create_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_pull_number_reviews", + mcp.WithDescription("Create a review for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithString("event", mcp.Description("Input parameter: The review action you want to perform. The review actions include: `APPROVE`, `REQUEST_CHANGES`, or `COMMENT`. By leaving this blank, you set the review action state to `PENDING`, which means you will need to [submit the pull request review](https://docs.github.com/rest/pulls/reviews#submit-a-review-for-a-pull-request) when you are ready.")), + mcp.WithString("body", mcp.Description("Input parameter: **Required** when using `REQUEST_CHANGES` or `COMMENT` for the `event` parameter. The body text of the pull request review.")), + mcp.WithArray("comments", mcp.Description("Input parameter: Use the following table to specify the location, destination, and contents of the draft review comment.")), + mcp.WithString("commit_id", mcp.Description("Input parameter: The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment outdated if a subsequent commit modifies the line you specify as the `position`. Defaults to the most recent commit in the pull request when you do not specify a value.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_create_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_create_review_comment.go b/MCP/tools/pulls/pulls_create_review_comment.go new file mode 100644 index 0000000..018c666 --- /dev/null +++ b/MCP/tools/pulls/pulls_create_review_comment.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_create_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/comments", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_create_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_pull_number_comments", + mcp.WithDescription("Create a review comment for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithString("start_side", mcp.Description("Input parameter: **Required when using multi-line comments unless using `in_reply_to`**. The `start_side` is the starting side of the diff that the comment applies to. Can be `LEFT` or `RIGHT`. To learn more about multi-line comments, see \"[Commenting on a pull request](https://docs.github.com/articles/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request)\" in the GitHub Help documentation. See `side` in this table for additional context.")), + mcp.WithString("commit_id", mcp.Required(), mcp.Description("Input parameter: The SHA of the commit needing a comment. Not using the latest commit SHA may render your comment outdated if a subsequent commit modifies the line you specify as the `position`.")), + mcp.WithString("path", mcp.Required(), mcp.Description("Input parameter: The relative path to the file that necessitates a comment.")), + mcp.WithNumber("position", mcp.Description("Input parameter: **This parameter is closing down. Use `line` instead**. The position in the diff where you want to add a review comment. Note this value is not the same as the line number in the file. The position value equals the number of lines down from the first \"@@\" hunk header in the file you want to add a comment. The line just below the \"@@\" line is position 1, the next line is position 2, and so on. The position in the diff continues to increase through lines of whitespace and additional hunks until the beginning of a new file.")), + mcp.WithString("subject_type", mcp.Description("Input parameter: The level at which the comment is targeted.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The text of the review comment.")), + mcp.WithNumber("in_reply_to", mcp.Description("Input parameter: The ID of the review comment to reply to. To find the ID of a review comment with [\"List review comments on a pull request\"](#list-review-comments-on-a-pull-request). When specified, all parameters other than `body` in the request body are ignored.")), + mcp.WithNumber("line", mcp.Description("Input parameter: **Required unless using `subject_type:file`**. The line of the blob in the pull request diff that the comment applies to. For a multi-line comment, the last line of the range that your comment applies to.")), + mcp.WithString("side", mcp.Description("Input parameter: In a split diff view, the side of the diff that the pull request's changes appear on. Can be `LEFT` or `RIGHT`. Use `LEFT` for deletions that appear in red. Use `RIGHT` for additions that appear in green or unchanged lines that appear in white and are shown for context. For a multi-line comment, side represents whether the last line of the comment range is a deletion or addition. For more information, see \"[Diff view options](https://docs.github.com/articles/about-comparing-branches-in-pull-requests#diff-view-options)\" in the GitHub Help documentation.")), + mcp.WithNumber("start_line", mcp.Description("Input parameter: **Required when using multi-line comments unless using `in_reply_to`**. The `start_line` is the first line in the pull request diff that your multi-line comment applies to. To learn more about multi-line comments, see \"[Commenting on a pull request](https://docs.github.com/articles/commenting-on-a-pull-request#adding-line-comments-to-a-pull-request)\" in the GitHub Help documentation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_create_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_delete_pending_review.go b/MCP/tools/pulls/pulls_delete_pending_review.go new file mode 100644 index 0000000..4bb7870 --- /dev/null +++ b/MCP/tools/pulls/pulls_delete_pending_review.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_delete_pending_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + review_idVal, ok := args["review_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: review_id"), nil + } + review_id, ok := review_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: review_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews/%s", cfg.BaseURL, owner, repo, pull_number, review_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_delete_pending_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_pulls_pull_number_reviews_review_id", + mcp.WithDescription("Delete a pending review for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("review_id", mcp.Required(), mcp.Description("The unique identifier of the review.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_delete_pending_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_delete_review_comment.go b/MCP/tools/pulls/pulls_delete_review_comment.go new file mode 100644 index 0000000..f406ab0 --- /dev/null +++ b/MCP/tools/pulls/pulls_delete_review_comment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_delete_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_delete_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_pulls_comments_comment_id", + mcp.WithDescription("Delete a review comment for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_delete_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_dismiss_review.go b/MCP/tools/pulls/pulls_dismiss_review.go new file mode 100644 index 0000000..ea15780 --- /dev/null +++ b/MCP/tools/pulls/pulls_dismiss_review.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_dismiss_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + review_idVal, ok := args["review_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: review_id"), nil + } + review_id, ok := review_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: review_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews/%s/dismissals", cfg.BaseURL, owner, repo, pull_number, review_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_dismiss_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_pulls_pull_number_reviews_review_id_dismissals", + mcp.WithDescription("Dismiss a review for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("review_id", mcp.Required(), mcp.Description("The unique identifier of the review.")), + mcp.WithString("event", mcp.Description("")), + mcp.WithString("message", mcp.Required(), mcp.Description("Input parameter: The message for the pull request review dismissal")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_dismiss_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_get.go b/MCP/tools/pulls/pulls_get.go new file mode 100644 index 0000000..7210632 --- /dev/null +++ b/MCP/tools/pulls/pulls_get.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number", + mcp.WithDescription("Get a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_getHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_get_review.go b/MCP/tools/pulls/pulls_get_review.go new file mode 100644 index 0000000..4474541 --- /dev/null +++ b/MCP/tools/pulls/pulls_get_review.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_get_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + review_idVal, ok := args["review_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: review_id"), nil + } + review_id, ok := review_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: review_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews/%s", cfg.BaseURL, owner, repo, pull_number, review_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_get_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_reviews_review_id", + mcp.WithDescription("Get a review for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("review_id", mcp.Required(), mcp.Description("The unique identifier of the review.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_get_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_get_review_comment.go b/MCP/tools/pulls/pulls_get_review_comment.go new file mode 100644 index 0000000..b922cde --- /dev/null +++ b/MCP/tools/pulls/pulls_get_review_comment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_get_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_get_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_comments_comment_id", + mcp.WithDescription("Get a review comment for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_get_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list.go b/MCP/tools/pulls/pulls_list.go new file mode 100644 index 0000000..42915a3 --- /dev/null +++ b/MCP/tools/pulls/pulls_list.go @@ -0,0 +1,120 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["head"]; ok { + queryParams = append(queryParams, fmt.Sprintf("head=%v", val)) + } + if val, ok := args["base"]; ok { + queryParams = append(queryParams, fmt.Sprintf("base=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls", + mcp.WithDescription("List pull requests"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("Either `open`, `closed`, or `all` to filter by state.")), + mcp.WithString("head", mcp.Description("Filter pulls by head user or head organization and branch name in the format of `user:ref-name` or `organization:ref-name`. For example: `github:new-script-format` or `octocat:test-branch`.")), + mcp.WithString("base", mcp.Description("Filter pulls by base branch name. Example: `gh-pages`.")), + mcp.WithString("sort", mcp.Description("What to sort results by. `popularity` will sort by the number of comments. `long-running` will sort by date created and will limit the results to pull requests that have been open for more than a month and have had activity within the past month.")), + mcp.WithString("direction", mcp.Description("The direction of the sort. Default: `desc` when sort is `created` or sort is not specified, otherwise `asc`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_listHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_comments_for_review.go b/MCP/tools/pulls/pulls_list_comments_for_review.go new file mode 100644 index 0000000..209819a --- /dev/null +++ b/MCP/tools/pulls/pulls_list_comments_for_review.go @@ -0,0 +1,118 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_comments_for_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + review_idVal, ok := args["review_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: review_id"), nil + } + review_id, ok := review_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: review_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews/%s/comments%s", cfg.BaseURL, owner, repo, pull_number, review_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_comments_for_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_reviews_review_id_comments", + mcp.WithDescription("List comments for a pull request review"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("review_id", mcp.Required(), mcp.Description("The unique identifier of the review.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_comments_for_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_commits.go b/MCP/tools/pulls/pulls_list_commits.go new file mode 100644 index 0000000..0fe0fa4 --- /dev/null +++ b/MCP/tools/pulls/pulls_list_commits.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_commitsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/commits%s", cfg.BaseURL, owner, repo, pull_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Commit + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_commitsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_commits", + mcp.WithDescription("List commits on a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_commitsHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_files.go b/MCP/tools/pulls/pulls_list_files.go new file mode 100644 index 0000000..bace302 --- /dev/null +++ b/MCP/tools/pulls/pulls_list_files.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_filesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/files%s", cfg.BaseURL, owner, repo, pull_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_filesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_files", + mcp.WithDescription("List pull requests files"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_filesHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_requested_reviewers.go b/MCP/tools/pulls/pulls_list_requested_reviewers.go new file mode 100644 index 0000000..dcddabb --- /dev/null +++ b/MCP/tools/pulls/pulls_list_requested_reviewers.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_requested_reviewersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/requested_reviewers", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_requested_reviewersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_requested_reviewers", + mcp.WithDescription("Get all requested reviewers for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_requested_reviewersHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_review_comments.go b/MCP/tools/pulls/pulls_list_review_comments.go new file mode 100644 index 0000000..84c7fe1 --- /dev/null +++ b/MCP/tools/pulls/pulls_list_review_comments.go @@ -0,0 +1,121 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_review_commentsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/comments%s", cfg.BaseURL, owner, repo, pull_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_review_commentsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_comments", + mcp.WithDescription("List review comments on a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("The direction to sort results. Ignored without `sort` parameter.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_review_commentsHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_review_comments_for_repo.go b/MCP/tools/pulls/pulls_list_review_comments_for_repo.go new file mode 100644 index 0000000..a888086 --- /dev/null +++ b/MCP/tools/pulls/pulls_list_review_comments_for_repo.go @@ -0,0 +1,112 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_review_comments_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_review_comments_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_comments", + mcp.WithDescription("List review comments in a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sort", mcp.Description("")), + mcp.WithString("direction", mcp.Description("The direction to sort results. Ignored without `sort` parameter.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_review_comments_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_list_reviews.go b/MCP/tools/pulls/pulls_list_reviews.go new file mode 100644 index 0000000..70500d2 --- /dev/null +++ b/MCP/tools/pulls/pulls_list_reviews.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_list_reviewsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews%s", cfg.BaseURL, owner, repo, pull_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_list_reviewsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_pull_number_reviews", + mcp.WithDescription("List reviews for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_list_reviewsHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_merge.go b/MCP/tools/pulls/pulls_merge.go new file mode 100644 index 0000000..84fa4db --- /dev/null +++ b/MCP/tools/pulls/pulls_merge.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_mergeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/merge", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_mergeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_pulls_pull_number_merge", + mcp.WithDescription("Merge a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithString("commit_title", mcp.Description("Input parameter: Title for the automatic commit message.")), + mcp.WithString("merge_method", mcp.Description("Input parameter: The merge method to use.")), + mcp.WithString("sha", mcp.Description("Input parameter: SHA that pull request head must match to allow merge.")), + mcp.WithString("commit_message", mcp.Description("Input parameter: Extra detail to append to automatic commit message.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_mergeHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_remove_requested_reviewers.go b/MCP/tools/pulls/pulls_remove_requested_reviewers.go new file mode 100644 index 0000000..9d4802a --- /dev/null +++ b/MCP/tools/pulls/pulls_remove_requested_reviewers.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_remove_requested_reviewersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/requested_reviewers", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_remove_requested_reviewersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_pulls_pull_number_requested_reviewers", + mcp.WithDescription("Remove requested reviewers from a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithArray("reviewers", mcp.Required(), mcp.Description("Input parameter: An array of user `login`s that will be removed.")), + mcp.WithArray("team_reviewers", mcp.Description("Input parameter: An array of team `slug`s that will be removed.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_remove_requested_reviewersHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_request_reviewers.go b/MCP/tools/pulls/pulls_request_reviewers.go new file mode 100644 index 0000000..41b4a06 --- /dev/null +++ b/MCP/tools/pulls/pulls_request_reviewers.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_request_reviewersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/requested_reviewers", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_request_reviewersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_pull_number_requested_reviewers", + mcp.WithDescription("Request reviewers for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithArray("reviewers", mcp.Description("Input parameter: An array of user `login`s that will be requested.")), + mcp.WithArray("team_reviewers", mcp.Description("Input parameter: An array of team `slug`s that will be requested.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_request_reviewersHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_submit_review.go b/MCP/tools/pulls/pulls_submit_review.go new file mode 100644 index 0000000..17e9cb6 --- /dev/null +++ b/MCP/tools/pulls/pulls_submit_review.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_submit_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + review_idVal, ok := args["review_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: review_id"), nil + } + review_id, ok := review_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: review_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews/%s/events", cfg.BaseURL, owner, repo, pull_number, review_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_submit_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_pull_number_reviews_review_id_events", + mcp.WithDescription("Submit a review for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("review_id", mcp.Required(), mcp.Description("The unique identifier of the review.")), + mcp.WithString("body", mcp.Description("Input parameter: The body text of the pull request review")), + mcp.WithString("event", mcp.Required(), mcp.Description("Input parameter: The review action you want to perform. The review actions include: `APPROVE`, `REQUEST_CHANGES`, or `COMMENT`. When you leave this blank, the API returns _HTTP 422 (Unrecognizable entity)_ and sets the review action state to `PENDING`, which means you will need to re-submit the pull request review using a review action.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_submit_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_update.go b/MCP/tools/pulls/pulls_update.go new file mode 100644 index 0000000..2a07f33 --- /dev/null +++ b/MCP/tools/pulls/pulls_update.go @@ -0,0 +1,118 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_pulls_pull_number", + mcp.WithDescription("Update a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithBoolean("maintainer_can_modify", mcp.Description("Input parameter: Indicates whether [maintainers can modify](https://docs.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/) the pull request.")), + mcp.WithString("state", mcp.Description("Input parameter: State of this Pull Request. Either `open` or `closed`.")), + mcp.WithString("title", mcp.Description("Input parameter: The title of the pull request.")), + mcp.WithString("base", mcp.Description("Input parameter: The name of the branch you want your changes pulled into. This should be an existing branch on the current repository. You cannot update the base branch on a pull request to point to another repository.")), + mcp.WithString("body", mcp.Description("Input parameter: The contents of the pull request.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_updateHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_update_branch.go b/MCP/tools/pulls/pulls_update_branch.go new file mode 100644 index 0000000..8b0b149 --- /dev/null +++ b/MCP/tools/pulls/pulls_update_branch.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_update_branchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/update-branch", cfg.BaseURL, owner, repo, pull_number) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_update_branchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_pulls_pull_number_update-branch", + mcp.WithDescription("Update a pull request branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithString("expected_head_sha", mcp.Description("Input parameter: The expected SHA of the pull request's HEAD ref. This is the most recent commit on the pull request's branch. If the expected SHA does not match the pull request's HEAD, you will receive a `422 Unprocessable Entity` status. You can use the \"[List commits](https://docs.github.com/rest/commits/commits#list-commits)\" endpoint to find the most recent commit SHA. Default: SHA of the pull request's current HEAD ref.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_update_branchHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_update_review.go b/MCP/tools/pulls/pulls_update_review.go new file mode 100644 index 0000000..1eb7a9c --- /dev/null +++ b/MCP/tools/pulls/pulls_update_review.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_update_reviewHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pull_numberVal, ok := args["pull_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pull_number"), nil + } + pull_number, ok := pull_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pull_number"), nil + } + review_idVal, ok := args["review_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: review_id"), nil + } + review_id, ok := review_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: review_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/%s/reviews/%s", cfg.BaseURL, owner, repo, pull_number, review_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_update_reviewTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_pulls_pull_number_reviews_review_id", + mcp.WithDescription("Update a review for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("pull_number", mcp.Required(), mcp.Description("The number that identifies the pull request.")), + mcp.WithNumber("review_id", mcp.Required(), mcp.Description("The unique identifier of the review.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The body text of the pull request review.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_update_reviewHandler(cfg), + } +} diff --git a/MCP/tools/pulls/pulls_update_review_comment.go b/MCP/tools/pulls/pulls_update_review_comment.go new file mode 100644 index 0000000..542c163 --- /dev/null +++ b/MCP/tools/pulls/pulls_update_review_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Pulls_update_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreatePulls_update_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_pulls_comments_comment_id", + mcp.WithDescription("Update a review comment for a pull request"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The text of the reply to the review comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Pulls_update_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/rate_limit/rate_limit_get.go b/MCP/tools/rate_limit/rate_limit_get.go new file mode 100644 index 0000000..fc97cd5 --- /dev/null +++ b/MCP/tools/rate_limit/rate_limit_get.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Rate_limit_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/rate_limit", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRate_limit_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_rate_limit", + mcp.WithDescription("Get rate limit status for the authenticated user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Rate_limit_getHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_commit_comment.go b/MCP/tools/reactions/reactions_create_for_commit_comment.go new file mode 100644 index 0000000..2fa1f57 --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_commit_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/comments/%s/reactions", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_comments_comment_id_reactions", + mcp.WithDescription("Create reaction for a commit comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the commit comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_issue.go b/MCP/tools/reactions/reactions_create_for_issue.go new file mode 100644 index 0000000..c4ba53d --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_issue.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/reactions", cfg.BaseURL, owner, repo, issue_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues_issue_number_reactions", + mcp.WithDescription("Create reaction for an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the issue.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_issueHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_issue_comment.go b/MCP/tools/reactions/reactions_create_for_issue_comment.go new file mode 100644 index 0000000..9bb8f64 --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_issue_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_issue_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments/%s/reactions", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_issue_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_issues_comments_comment_id_reactions", + mcp.WithDescription("Create reaction for an issue comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the issue comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_issue_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_pull_request_review_comment.go b/MCP/tools/reactions/reactions_create_for_pull_request_review_comment.go new file mode 100644 index 0000000..bac2cdc --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_pull_request_review_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_pull_request_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments/%s/reactions", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_pull_request_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pulls_comments_comment_id_reactions", + mcp.WithDescription("Create reaction for a pull request review comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the pull request review comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_pull_request_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_release.go b/MCP/tools/reactions/reactions_create_for_release.go new file mode 100644 index 0000000..c7fe3df --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_release.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s/reactions", cfg.BaseURL, owner, repo, release_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_releases_release_id_reactions", + mcp.WithDescription("Create reaction for a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the release.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_releaseHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_team_discussion_comment_in_org.go b/MCP/tools/reactions/reactions_create_for_team_discussion_comment_in_org.go new file mode 100644 index 0000000..96ff70f --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_team_discussion_comment_in_org.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_team_discussion_comment_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments/%s/reactions", cfg.BaseURL, org, team_slug, discussion_number, comment_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_team_discussion_comment_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_teams_team_slug_discussions_discussion_number_comments_comment_number_reactions", + mcp.WithDescription("Create reaction for a team discussion comment"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the team discussion comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_team_discussion_comment_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_team_discussion_comment_legacy.go b/MCP/tools/reactions/reactions_create_for_team_discussion_comment_legacy.go new file mode 100644 index 0000000..5a10a62 --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_team_discussion_comment_legacy.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_team_discussion_comment_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments/%s/reactions", cfg.BaseURL, team_id, discussion_number, comment_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_team_discussion_comment_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_teams_team_id_discussions_discussion_number_comments_comment_number_reactions", + mcp.WithDescription("Create reaction for a team discussion comment (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the team discussion comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_team_discussion_comment_legacyHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_team_discussion_in_org.go b/MCP/tools/reactions/reactions_create_for_team_discussion_in_org.go new file mode 100644 index 0000000..993a4b7 --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_team_discussion_in_org.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_team_discussion_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/reactions", cfg.BaseURL, org, team_slug, discussion_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_team_discussion_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_teams_team_slug_discussions_discussion_number_reactions", + mcp.WithDescription("Create reaction for a team discussion"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the team discussion.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_team_discussion_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_create_for_team_discussion_legacy.go b/MCP/tools/reactions/reactions_create_for_team_discussion_legacy.go new file mode 100644 index 0000000..83addfc --- /dev/null +++ b/MCP/tools/reactions/reactions_create_for_team_discussion_legacy.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_create_for_team_discussion_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/reactions", cfg.BaseURL, team_id, discussion_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_create_for_team_discussion_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_teams_team_id_discussions_discussion_number_reactions", + mcp.WithDescription("Create reaction for a team discussion (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions) to add to the team discussion.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_create_for_team_discussion_legacyHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_commit_comment.go b/MCP/tools/reactions/reactions_delete_for_commit_comment.go new file mode 100644 index 0000000..d68e7bd --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_commit_comment.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/comments/%s/reactions/%s", cfg.BaseURL, owner, repo, comment_id, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_comments_comment_id_reactions_reaction_id", + mcp.WithDescription("Delete a commit comment reaction"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_issue.go b/MCP/tools/reactions/reactions_delete_for_issue.go new file mode 100644 index 0000000..c87c5df --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_issue.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/reactions/%s", cfg.BaseURL, owner, repo, issue_number, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_issue_number_reactions_reaction_id", + mcp.WithDescription("Delete an issue reaction"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_issueHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_issue_comment.go b/MCP/tools/reactions/reactions_delete_for_issue_comment.go new file mode 100644 index 0000000..e4760f1 --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_issue_comment.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_issue_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments/%s/reactions/%s", cfg.BaseURL, owner, repo, comment_id, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_issue_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_issues_comments_comment_id_reactions_reaction_id", + mcp.WithDescription("Delete an issue comment reaction"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_issue_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_pull_request_comment.go b/MCP/tools/reactions/reactions_delete_for_pull_request_comment.go new file mode 100644 index 0000000..bf9c11d --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_pull_request_comment.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_pull_request_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments/%s/reactions/%s", cfg.BaseURL, owner, repo, comment_id, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_pull_request_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_pulls_comments_comment_id_reactions_reaction_id", + mcp.WithDescription("Delete a pull request comment reaction"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_pull_request_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_release.go b/MCP/tools/reactions/reactions_delete_for_release.go new file mode 100644 index 0000000..6256c63 --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_release.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s/reactions/%s", cfg.BaseURL, owner, repo, release_id, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_releases_release_id_reactions_reaction_id", + mcp.WithDescription("Delete a release reaction"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_releaseHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_team_discussion.go b/MCP/tools/reactions/reactions_delete_for_team_discussion.go new file mode 100644 index 0000000..8cdfb20 --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_team_discussion.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_team_discussionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/reactions/%s", cfg.BaseURL, org, team_slug, discussion_number, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_team_discussionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_discussions_discussion_number_reactions_reaction_id", + mcp.WithDescription("Delete team discussion reaction"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_team_discussionHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_delete_for_team_discussion_comment.go b/MCP/tools/reactions/reactions_delete_for_team_discussion_comment.go new file mode 100644 index 0000000..36fa877 --- /dev/null +++ b/MCP/tools/reactions/reactions_delete_for_team_discussion_comment.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_delete_for_team_discussion_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + reaction_idVal, ok := args["reaction_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: reaction_id"), nil + } + reaction_id, ok := reaction_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: reaction_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments/%s/reactions/%s", cfg.BaseURL, org, team_slug, discussion_number, comment_number, reaction_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_delete_for_team_discussion_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_discussions_discussion_number_comments_comment_number_reactions_reaction_id", + mcp.WithDescription("Delete team discussion comment reaction"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithNumber("reaction_id", mcp.Required(), mcp.Description("The unique identifier of the reaction.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_delete_for_team_discussion_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_commit_comment.go b/MCP/tools/reactions/reactions_list_for_commit_comment.go new file mode 100644 index 0000000..b391ce7 --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_commit_comment.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/comments/%s/reactions%s", cfg.BaseURL, owner, repo, comment_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_comments_comment_id_reactions", + mcp.WithDescription("List reactions for a commit comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a commit comment.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_issue.go b/MCP/tools/reactions/reactions_list_for_issue.go new file mode 100644 index 0000000..48bba3e --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_issue.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_issueHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + issue_numberVal, ok := args["issue_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: issue_number"), nil + } + issue_number, ok := issue_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: issue_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/%s/reactions%s", cfg.BaseURL, owner, repo, issue_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_issueTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_issue_number_reactions", + mcp.WithDescription("List reactions for an issue"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("issue_number", mcp.Required(), mcp.Description("The number that identifies the issue.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to an issue.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_issueHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_issue_comment.go b/MCP/tools/reactions/reactions_list_for_issue_comment.go new file mode 100644 index 0000000..19688e9 --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_issue_comment.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_issue_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/issues/comments/%s/reactions%s", cfg.BaseURL, owner, repo, comment_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_issue_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_issues_comments_comment_id_reactions", + mcp.WithDescription("List reactions for an issue comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to an issue comment.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_issue_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_pull_request_review_comment.go b/MCP/tools/reactions/reactions_list_for_pull_request_review_comment.go new file mode 100644 index 0000000..971bc2c --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_pull_request_review_comment.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_pull_request_review_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pulls/comments/%s/reactions%s", cfg.BaseURL, owner, repo, comment_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_pull_request_review_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pulls_comments_comment_id_reactions", + mcp.WithDescription("List reactions for a pull request review comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a pull request review comment.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_pull_request_review_commentHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_release.go b/MCP/tools/reactions/reactions_list_for_release.go new file mode 100644 index 0000000..8c1d5b6 --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_release.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s/reactions%s", cfg.BaseURL, owner, repo, release_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases_release_id_reactions", + mcp.WithDescription("List reactions for a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a release.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_releaseHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_team_discussion_comment_in_org.go b/MCP/tools/reactions/reactions_list_for_team_discussion_comment_in_org.go new file mode 100644 index 0000000..36a9213 --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_team_discussion_comment_in_org.go @@ -0,0 +1,122 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_team_discussion_comment_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments/%s/reactions%s", cfg.BaseURL, org, team_slug, discussion_number, comment_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_team_discussion_comment_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_discussions_discussion_number_comments_comment_number_reactions", + mcp.WithDescription("List reactions for a team discussion comment"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a team discussion comment.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_team_discussion_comment_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_team_discussion_comment_legacy.go b/MCP/tools/reactions/reactions_list_for_team_discussion_comment_legacy.go new file mode 100644 index 0000000..ccb0400 --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_team_discussion_comment_legacy.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_team_discussion_comment_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments/%s/reactions%s", cfg.BaseURL, team_id, discussion_number, comment_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_team_discussion_comment_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_discussions_discussion_number_comments_comment_number_reactions", + mcp.WithDescription("List reactions for a team discussion comment (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a team discussion comment.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_team_discussion_comment_legacyHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_team_discussion_in_org.go b/MCP/tools/reactions/reactions_list_for_team_discussion_in_org.go new file mode 100644 index 0000000..98e7d28 --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_team_discussion_in_org.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_team_discussion_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/reactions%s", cfg.BaseURL, org, team_slug, discussion_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_team_discussion_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_discussions_discussion_number_reactions", + mcp.WithDescription("List reactions for a team discussion"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a team discussion.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_team_discussion_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/reactions/reactions_list_for_team_discussion_legacy.go b/MCP/tools/reactions/reactions_list_for_team_discussion_legacy.go new file mode 100644 index 0000000..d91e81b --- /dev/null +++ b/MCP/tools/reactions/reactions_list_for_team_discussion_legacy.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Reactions_list_for_team_discussion_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["content"]; ok { + queryParams = append(queryParams, fmt.Sprintf("content=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/reactions%s", cfg.BaseURL, team_id, discussion_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Reaction + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateReactions_list_for_team_discussion_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_discussions_discussion_number_reactions", + mcp.WithDescription("List reactions for a team discussion (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("content", mcp.Description("Returns a single [reaction type](https://docs.github.com/rest/reactions/reactions#about-reactions). Omit this parameter to list all reactions to a team discussion.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Reactions_list_for_team_discussion_legacyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_accept_invitation_for_authenticated_user.go b/MCP/tools/repos/repos_accept_invitation_for_authenticated_user.go new file mode 100644 index 0000000..6932695 --- /dev/null +++ b/MCP/tools/repos/repos_accept_invitation_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_accept_invitation_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + invitation_idVal, ok := args["invitation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: invitation_id"), nil + } + invitation_id, ok := invitation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: invitation_id"), nil + } + url := fmt.Sprintf("%s/user/repository_invitations/%s", cfg.BaseURL, invitation_id) + req, err := http.NewRequest("PATCH", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_accept_invitation_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_user_repository_invitations_invitation_id", + mcp.WithDescription("Accept a repository invitation"), + mcp.WithNumber("invitation_id", mcp.Required(), mcp.Description("The unique identifier of the invitation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_accept_invitation_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_add_app_access_restrictions.go b/MCP/tools/repos/repos_add_app_access_restrictions.go new file mode 100644 index 0000000..5943b0e --- /dev/null +++ b/MCP/tools/repos/repos_add_app_access_restrictions.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_add_app_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/apps", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Integration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_add_app_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_protection_restrictions_apps", + mcp.WithDescription("Add app access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("apps", mcp.Required(), mcp.Description("Input parameter: The GitHub Apps that have push access to this branch. Use the slugified version of the app name. **Note**: The list of users, apps, and teams in total is limited to 100 items.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_add_app_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_add_collaborator.go b/MCP/tools/repos/repos_add_collaborator.go new file mode 100644 index 0000000..f487d47 --- /dev/null +++ b/MCP/tools/repos/repos_add_collaborator.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_add_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/collaborators/%s", cfg.BaseURL, owner, repo, username) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_add_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_collaborators_username", + mcp.WithDescription("Add a repository collaborator"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("permission", mcp.Description("Input parameter: The permission to grant the collaborator. **Only valid on organization-owned repositories.** We accept the following permissions to be set: `pull`, `triage`, `push`, `maintain`, `admin` and you can also specify a custom repository role name, if the owning organization has defined any.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_add_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_add_status_check_contexts.go b/MCP/tools/repos/repos_add_status_check_contexts.go new file mode 100644 index 0000000..9195f03 --- /dev/null +++ b/MCP/tools/repos/repos_add_status_check_contexts.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_add_status_check_contextsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks/contexts", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_add_status_check_contextsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_protection_required_status_checks_contexts", + mcp.WithDescription("Add status check contexts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_add_status_check_contextsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_add_team_access_restrictions.go b/MCP/tools/repos/repos_add_team_access_restrictions.go new file mode 100644 index 0000000..c3687b9 --- /dev/null +++ b/MCP/tools/repos/repos_add_team_access_restrictions.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_add_team_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/teams", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_add_team_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_protection_restrictions_teams", + mcp.WithDescription("Add team access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_add_team_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_add_user_access_restrictions.go b/MCP/tools/repos/repos_add_user_access_restrictions.go new file mode 100644 index 0000000..dc93a8d --- /dev/null +++ b/MCP/tools/repos/repos_add_user_access_restrictions.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_add_user_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/users", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_add_user_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_protection_restrictions_users", + mcp.WithDescription("Add user access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("users", mcp.Required(), mcp.Description("Input parameter: The username for users")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_add_user_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_cancel_pages_deployment.go b/MCP/tools/repos/repos_cancel_pages_deployment.go new file mode 100644 index 0000000..6ff3ddb --- /dev/null +++ b/MCP/tools/repos/repos_cancel_pages_deployment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_cancel_pages_deploymentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pages_deployment_idVal, ok := args["pages_deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pages_deployment_id"), nil + } + pages_deployment_id, ok := pages_deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pages_deployment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/deployments/%s/cancel", cfg.BaseURL, owner, repo, pages_deployment_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_cancel_pages_deploymentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pages_deployments_pages_deployment_id_cancel", + mcp.WithDescription("Cancel a GitHub Pages deployment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("pages_deployment_id", mcp.Required(), mcp.Description("The ID of the Pages deployment. You can also give the commit SHA of the deployment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_cancel_pages_deploymentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_check_automated_security_fixes.go b/MCP/tools/repos/repos_check_automated_security_fixes.go new file mode 100644 index 0000000..ee67e6b --- /dev/null +++ b/MCP/tools/repos/repos_check_automated_security_fixes.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_check_automated_security_fixesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/automated-security-fixes", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_check_automated_security_fixesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_automated-security-fixes", + mcp.WithDescription("Check if Dependabot security updates are enabled for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_check_automated_security_fixesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_check_collaborator.go b/MCP/tools/repos/repos_check_collaborator.go new file mode 100644 index 0000000..70bdf05 --- /dev/null +++ b/MCP/tools/repos/repos_check_collaborator.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_check_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/collaborators/%s", cfg.BaseURL, owner, repo, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_check_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_collaborators_username", + mcp.WithDescription("Check if a user is a repository collaborator"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_check_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_check_private_vulnerability_reporting.go b/MCP/tools/repos/repos_check_private_vulnerability_reporting.go new file mode 100644 index 0000000..ac0b10a --- /dev/null +++ b/MCP/tools/repos/repos_check_private_vulnerability_reporting.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_check_private_vulnerability_reportingHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/private-vulnerability-reporting", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_check_private_vulnerability_reportingTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_private-vulnerability-reporting", + mcp.WithDescription("Check if private vulnerability reporting is enabled for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_check_private_vulnerability_reportingHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_check_vulnerability_alerts.go b/MCP/tools/repos/repos_check_vulnerability_alerts.go new file mode 100644 index 0000000..3430814 --- /dev/null +++ b/MCP/tools/repos/repos_check_vulnerability_alerts.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_check_vulnerability_alertsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/vulnerability-alerts", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_check_vulnerability_alertsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_vulnerability-alerts", + mcp.WithDescription("Check if vulnerability alerts are enabled for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_check_vulnerability_alertsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_codeowners_errors.go b/MCP/tools/repos/repos_codeowners_errors.go new file mode 100644 index 0000000..d8a69d7 --- /dev/null +++ b/MCP/tools/repos/repos_codeowners_errors.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_codeowners_errorsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/codeowners/errors%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_codeowners_errorsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_codeowners_errors", + mcp.WithDescription("List CODEOWNERS errors"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Description("A branch, tag or commit name used to determine which version of the CODEOWNERS file to use. Default: the repository's default branch (e.g. `main`)")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_codeowners_errorsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_compare_commits.go b/MCP/tools/repos/repos_compare_commits.go new file mode 100644 index 0000000..9478467 --- /dev/null +++ b/MCP/tools/repos/repos_compare_commits.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_compare_commitsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + baseheadVal, ok := args["basehead"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: basehead"), nil + } + basehead, ok := baseheadVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: basehead"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/compare/%s%s", cfg.BaseURL, owner, repo, basehead, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_compare_commitsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_compare_basehead", + mcp.WithDescription("Compare two commits"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("basehead", mcp.Required(), mcp.Description("The base branch and head branch to compare. This parameter expects the format `BASE...HEAD`. Both must be branch names in `repo`. To compare with a branch that exists in a different repository in the same network as `repo`, the `basehead` parameter expects the format `USERNAME:BASE...USERNAME:HEAD`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_compare_commitsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_attestation.go b/MCP/tools/repos/repos_create_attestation.go new file mode 100644 index 0000000..706267d --- /dev/null +++ b/MCP/tools/repos/repos_create_attestation.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_attestationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/attestations", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_attestationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_attestations", + mcp.WithDescription("Create an attestation"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithObject("bundle", mcp.Required(), mcp.Description("Input parameter: The attestation's Sigstore Bundle.\nRefer to the [Sigstore Bundle Specification](https://github.com/sigstore/protobuf-specs/blob/main/protos/sigstore_bundle.proto) for more information.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_attestationHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_autolink.go b/MCP/tools/repos/repos_create_autolink.go new file mode 100644 index 0000000..a0ef1f8 --- /dev/null +++ b/MCP/tools/repos/repos_create_autolink.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_autolinkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/autolinks", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Autolink + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_autolinkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_autolinks", + mcp.WithDescription("Create an autolink reference for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("is_alphanumeric", mcp.Description("Input parameter: Whether this autolink reference matches alphanumeric characters. If true, the `` parameter of the `url_template` matches alphanumeric characters `A-Z` (case insensitive), `0-9`, and `-`. If false, this autolink reference only matches numeric characters.")), + mcp.WithString("key_prefix", mcp.Required(), mcp.Description("Input parameter: This prefix appended by certain characters will generate a link any time it is found in an issue, pull request, or commit.")), + mcp.WithString("url_template", mcp.Required(), mcp.Description("Input parameter: The URL must contain `` for the reference number. `` matches different characters depending on the value of `is_alphanumeric`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_autolinkHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_commit_comment.go b/MCP/tools/repos/repos_create_commit_comment.go new file mode 100644 index 0000000..3ac7b67 --- /dev/null +++ b/MCP/tools/repos/repos_create_commit_comment.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + commit_shaVal, ok := args["commit_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: commit_sha"), nil + } + commit_sha, ok := commit_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: commit_sha"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/comments", cfg.BaseURL, owner, repo, commit_sha) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_commits_commit_sha_comments", + mcp.WithDescription("Create a commit comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("commit_sha", mcp.Required(), mcp.Description("The SHA of the commit.")), + mcp.WithString("path", mcp.Description("Input parameter: Relative path of the file to comment on.")), + mcp.WithNumber("position", mcp.Description("Input parameter: Line index in the diff to comment on.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The contents of the comment.")), + mcp.WithNumber("line", mcp.Description("Input parameter: **Closing down notice**. Use **position** parameter instead. Line number in the file to comment on.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_commit_signature_protection.go b/MCP/tools/repos/repos_create_commit_signature_protection.go new file mode 100644 index 0000000..d87e035 --- /dev/null +++ b/MCP/tools/repos/repos_create_commit_signature_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_commit_signature_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_signatures", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_commit_signature_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_protection_required_signatures", + mcp.WithDescription("Create commit signature protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_commit_signature_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_commit_status.go b/MCP/tools/repos/repos_create_commit_status.go new file mode 100644 index 0000000..f2b09e5 --- /dev/null +++ b/MCP/tools/repos/repos_create_commit_status.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_commit_statusHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + shaVal, ok := args["sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: sha"), nil + } + sha, ok := shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: sha"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/statuses/%s", cfg.BaseURL, owner, repo, sha) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Status + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_commit_statusTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_statuses_sha", + mcp.WithDescription("Create a commit status"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("")), + mcp.WithString("target_url", mcp.Description("Input parameter: The target URL to associate with this status. This URL will be linked from the GitHub UI to allow users to easily see the source of the status. \nFor example, if your continuous integration system is posting build status, you would want to provide the deep link for the build output for this specific SHA: \n`http://ci.example.com/user/repo/build/sha`")), + mcp.WithString("context", mcp.Description("Input parameter: A string label to differentiate this status from the status of other systems. This field is case-insensitive.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the status.")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: The state of the status.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_commit_statusHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_deploy_key.go b/MCP/tools/repos/repos_create_deploy_key.go new file mode 100644 index 0000000..48c2729 --- /dev/null +++ b/MCP/tools/repos/repos_create_deploy_key.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_deploy_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/keys", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_deploy_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_keys", + mcp.WithDescription("Create a deploy key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("key", mcp.Required(), mcp.Description("Input parameter: The contents of the key.")), + mcp.WithBoolean("read_only", mcp.Description("Input parameter: If `true`, the key will only be able to read repository contents. Otherwise, the key will be able to read and write. \n \nDeploy keys with write access can perform the same actions as an organization member with admin access, or a collaborator on a personal repository. For more information, see \"[Repository permission levels for an organization](https://docs.github.com/articles/repository-permission-levels-for-an-organization/)\" and \"[Permission levels for a user account repository](https://docs.github.com/articles/permission-levels-for-a-user-account-repository/).\"")), + mcp.WithString("title", mcp.Description("Input parameter: A name for the key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_deploy_keyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_deployment.go b/MCP/tools/repos/repos_create_deployment.go new file mode 100644 index 0000000..43646b2 --- /dev/null +++ b/MCP/tools/repos/repos_create_deployment.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_deploymentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Deployment + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_deploymentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_deployments", + mcp.WithDescription("Create a deployment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("payload", mcp.Description("")), + mcp.WithArray("required_contexts", mcp.Description("Input parameter: The [status](https://docs.github.com/rest/commits/statuses) contexts to verify against commit status checks. If you omit this parameter, GitHub verifies all unique contexts before creating a deployment. To bypass checking entirely, pass an empty array. Defaults to all unique contexts.")), + mcp.WithBoolean("transient_environment", mcp.Description("Input parameter: Specifies if the given environment is specific to the deployment and will no longer exist at some point in the future. Default: `false`")), + mcp.WithBoolean("auto_merge", mcp.Description("Input parameter: Attempts to automatically merge the default branch into the requested ref, if it's behind the default branch.")), + mcp.WithString("description", mcp.Description("Input parameter: Short description of the deployment.")), + mcp.WithString("environment", mcp.Description("Input parameter: Name for the target deployment environment (e.g., `production`, `staging`, `qa`).")), + mcp.WithBoolean("production_environment", mcp.Description("Input parameter: Specifies if the given environment is one that end-users directly interact with. Default: `true` when `environment` is `production` and `false` otherwise.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("Input parameter: The ref to deploy. This can be a branch, tag, or SHA.")), + mcp.WithString("task", mcp.Description("Input parameter: Specifies a task to execute (e.g., `deploy` or `deploy:migrations`).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_deploymentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_deployment_branch_policy.go b/MCP/tools/repos/repos_create_deployment_branch_policy.go new file mode 100644 index 0000000..d3564da --- /dev/null +++ b/MCP/tools/repos/repos_create_deployment_branch_policy.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_deployment_branch_policyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment-branch-policies", cfg.BaseURL, owner, repo, environment_name) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_deployment_branch_policyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_environments_environment_name_deployment-branch-policies", + mcp.WithDescription("Create a deployment branch policy"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("type", mcp.Description("Input parameter: Whether this rule targets a branch or tag")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name pattern that branches or tags must match in order to deploy to the environment.\n\nWildcard characters will not match `/`. For example, to match branches that begin with `release/` and contain an additional single slash, use `release/*/*`.\nFor more information about pattern matching syntax, see the [Ruby File.fnmatch documentation](https://ruby-doc.org/core-2.5.1/File.html#method-c-fnmatch).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_deployment_branch_policyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_deployment_protection_rule.go b/MCP/tools/repos/repos_create_deployment_protection_rule.go new file mode 100644 index 0000000..1427821 --- /dev/null +++ b/MCP/tools/repos/repos_create_deployment_protection_rule.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_deployment_protection_ruleHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment_protection_rules", cfg.BaseURL, environment_name, repo, owner) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_deployment_protection_ruleTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_environments_environment_name_deployment_protection_rules", + mcp.WithDescription("Create a custom deployment protection rule on an environment"), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithNumber("integration_id", mcp.Description("Input parameter: The ID of the custom app that will be enabled on the environment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_deployment_protection_ruleHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_deployment_status.go b/MCP/tools/repos/repos_create_deployment_status.go new file mode 100644 index 0000000..dde53e1 --- /dev/null +++ b/MCP/tools/repos/repos_create_deployment_status.go @@ -0,0 +1,120 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_deployment_statusHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + deployment_idVal, ok := args["deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: deployment_id"), nil + } + deployment_id, ok := deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: deployment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments/%s/statuses", cfg.BaseURL, owner, repo, deployment_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_deployment_statusTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_deployments_deployment_id_statuses", + mcp.WithDescription("Create a deployment status"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("deployment_id", mcp.Required(), mcp.Description("deployment_id parameter")), + mcp.WithBoolean("auto_inactive", mcp.Description("Input parameter: Adds a new `inactive` status to all prior non-transient, non-production environment deployments with the same repository and `environment` name as the created status's deployment. An `inactive` status is only added to deployments that had a `success` state. Default: `true`")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the status. The maximum description length is 140 characters.")), + mcp.WithString("environment", mcp.Description("Input parameter: Name for the target deployment environment, which can be changed when setting a deploy status. For example, `production`, `staging`, or `qa`. If not defined, the environment of the previous status on the deployment will be used, if it exists. Otherwise, the environment of the deployment will be used.")), + mcp.WithString("environment_url", mcp.Description("Input parameter: Sets the URL for accessing your environment. Default: `\"\"`")), + mcp.WithString("log_url", mcp.Description("Input parameter: The full URL of the deployment's output. This parameter replaces `target_url`. We will continue to accept `target_url` to support legacy uses, but we recommend replacing `target_url` with `log_url`. Setting `log_url` will automatically set `target_url` to the same value. Default: `\"\"`")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: The state of the status. When you set a transient deployment to `inactive`, the deployment will be shown as `destroyed` in GitHub.")), + mcp.WithString("target_url", mcp.Description("Input parameter: The target URL to associate with this status. This URL should contain output to keep the user updated while the task is running or serve as historical information for what happened in the deployment.\n\n> [!NOTE]\n> It's recommended to use the `log_url` parameter, which replaces `target_url`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_deployment_statusHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_dispatch_event.go b/MCP/tools/repos/repos_create_dispatch_event.go new file mode 100644 index 0000000..0537442 --- /dev/null +++ b/MCP/tools/repos/repos_create_dispatch_event.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_dispatch_eventHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/dispatches", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_dispatch_eventTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_dispatches", + mcp.WithDescription("Create a repository dispatch event"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("event_type", mcp.Required(), mcp.Description("Input parameter: A custom webhook event name. Must be 100 characters or fewer.")), + mcp.WithObject("client_payload", mcp.Description("Input parameter: JSON payload with extra information about the webhook event that your action or workflow may use. The maximum number of top-level properties is 10. The total size of the JSON payload must be less than 64KB.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_dispatch_eventHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_for_authenticated_user.go b/MCP/tools/repos/repos_create_for_authenticated_user.go new file mode 100644 index 0000000..4641cf3 --- /dev/null +++ b/MCP/tools/repos/repos_create_for_authenticated_user.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/repos", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_repos", + mcp.WithDescription("Create a repository for the authenticated user"), + mcp.WithBoolean("allow_rebase_merge", mcp.Description("Input parameter: Whether to allow rebase merges for pull requests.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the repository.")), + mcp.WithBoolean("has_issues", mcp.Description("Input parameter: Whether issues are enabled.")), + mcp.WithString("merge_commit_message", mcp.Description("Input parameter: The default value for a merge commit message.\n\n- `PR_TITLE` - default to the pull request's title.\n- `PR_BODY` - default to the pull request's body.\n- `BLANK` - default to a blank commit message.")), + mcp.WithString("squash_merge_commit_message", mcp.Description("Input parameter: The default value for a squash merge commit message:\n\n- `PR_BODY` - default to the pull request's body.\n- `COMMIT_MESSAGES` - default to the branch's commit messages.\n- `BLANK` - default to a blank commit message.")), + mcp.WithBoolean("is_template", mcp.Description("Input parameter: Whether this repository acts as a template that can be used to generate new repositories.")), + mcp.WithBoolean("allow_merge_commit", mcp.Description("Input parameter: Whether to allow merge commits for pull requests.")), + mcp.WithBoolean("allow_auto_merge", mcp.Description("Input parameter: Whether to allow Auto-merge to be used on pull requests.")), + mcp.WithString("squash_merge_commit_title", mcp.Description("Input parameter: Required when using `squash_merge_commit_message`.\n\nThe default value for a squash merge commit title:\n\n- `PR_TITLE` - default to the pull request's title.\n- `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit).")), + mcp.WithBoolean("delete_branch_on_merge", mcp.Description("Input parameter: Whether to delete head branches when pull requests are merged")), + mcp.WithString("gitignore_template", mcp.Description("Input parameter: The desired language or platform to apply to the .gitignore.")), + mcp.WithString("merge_commit_title", mcp.Description("Input parameter: Required when using `merge_commit_message`.\n\nThe default value for a merge commit title.\n\n- `PR_TITLE` - default to the pull request's title.\n- `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name).")), + mcp.WithBoolean("auto_init", mcp.Description("Input parameter: Whether the repository is initialized with a minimal README.")), + mcp.WithBoolean("has_projects", mcp.Description("Input parameter: Whether projects are enabled.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Whether the repository is private.")), + mcp.WithBoolean("has_discussions", mcp.Description("Input parameter: Whether discussions are enabled.")), + mcp.WithNumber("team_id", mcp.Description("Input parameter: The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization.")), + mcp.WithBoolean("has_wiki", mcp.Description("Input parameter: Whether the wiki is enabled.")), + mcp.WithString("license_template", mcp.Description("Input parameter: The license keyword of the open source license for this repository.")), + mcp.WithBoolean("has_downloads", mcp.Description("Input parameter: Whether downloads are enabled.")), + mcp.WithBoolean("allow_squash_merge", mcp.Description("Input parameter: Whether to allow squash merges for pull requests.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the repository.")), + mcp.WithString("homepage", mcp.Description("Input parameter: A URL with more information about the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_fork.go b/MCP/tools/repos/repos_create_fork.go new file mode 100644 index 0000000..4fba668 --- /dev/null +++ b/MCP/tools/repos/repos_create_fork.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_forkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/forks", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_forkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_forks", + mcp.WithDescription("Create a fork"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("default_branch_only", mcp.Description("Input parameter: When forking from an existing repository, fork with only the default branch.")), + mcp.WithString("name", mcp.Description("Input parameter: When forking from an existing repository, a new name for the fork.")), + mcp.WithString("organization", mcp.Description("Input parameter: Optional parameter to specify the organization name if forking into an organization.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_forkHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_in_org.go b/MCP/tools/repos/repos_create_in_org.go new file mode 100644 index 0000000..9b02695 --- /dev/null +++ b/MCP/tools/repos/repos_create_in_org.go @@ -0,0 +1,120 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/repos", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_repos", + mcp.WithDescription("Create an organization repository"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the repository.")), + mcp.WithBoolean("use_squash_pr_title_as_default", mcp.Description("Input parameter: Either `true` to allow squash-merge commits to use pull request title, or `false` to use commit message. **This property is closing down. Please use `squash_merge_commit_title` instead.")), + mcp.WithBoolean("allow_merge_commit", mcp.Description("Input parameter: Either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits.")), + mcp.WithBoolean("has_projects", mcp.Description("Input parameter: Either `true` to enable projects for this repository or `false` to disable them. **Note:** If you're creating a repository in an organization that has disabled repository projects, the default is `false`, and if you pass `true`, the API returns an error.")), + mcp.WithString("merge_commit_message", mcp.Description("Input parameter: The default value for a merge commit message.\n\n- `PR_TITLE` - default to the pull request's title.\n- `PR_BODY` - default to the pull request's body.\n- `BLANK` - default to a blank commit message.")), + mcp.WithNumber("team_id", mcp.Description("Input parameter: The id of the team that will be granted access to this repository. This is only valid when creating a repository in an organization.")), + mcp.WithBoolean("auto_init", mcp.Description("Input parameter: Pass `true` to create an initial commit with empty README.")), + mcp.WithBoolean("allow_auto_merge", mcp.Description("Input parameter: Either `true` to allow auto-merge on pull requests, or `false` to disallow auto-merge.")), + mcp.WithBoolean("allow_squash_merge", mcp.Description("Input parameter: Either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Whether the repository is private.")), + mcp.WithString("squash_merge_commit_message", mcp.Description("Input parameter: The default value for a squash merge commit message:\n\n- `PR_BODY` - default to the pull request's body.\n- `COMMIT_MESSAGES` - default to the branch's commit messages.\n- `BLANK` - default to a blank commit message.")), + mcp.WithBoolean("allow_rebase_merge", mcp.Description("Input parameter: Either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging.")), + mcp.WithBoolean("is_template", mcp.Description("Input parameter: Either `true` to make this repo available as a template repository or `false` to prevent it.")), + mcp.WithString("license_template", mcp.Description("Input parameter: Choose an [open source license template](https://choosealicense.com/) that best suits your needs, and then use the [license keyword](https://docs.github.com/articles/licensing-a-repository/#searching-github-by-license-type) as the `license_template` string. For example, \"mit\" or \"mpl-2.0\".")), + mcp.WithBoolean("has_wiki", mcp.Description("Input parameter: Either `true` to enable the wiki for this repository or `false` to disable it.")), + mcp.WithString("squash_merge_commit_title", mcp.Description("Input parameter: Required when using `squash_merge_commit_message`.\n\nThe default value for a squash merge commit title:\n\n- `PR_TITLE` - default to the pull request's title.\n- `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit).")), + mcp.WithString("homepage", mcp.Description("Input parameter: A URL with more information about the repository.")), + mcp.WithBoolean("has_downloads", mcp.Description("Input parameter: Whether downloads are enabled.")), + mcp.WithBoolean("has_issues", mcp.Description("Input parameter: Either `true` to enable issues for this repository or `false` to disable them.")), + mcp.WithString("visibility", mcp.Description("Input parameter: The visibility of the repository.")), + mcp.WithBoolean("delete_branch_on_merge", mcp.Description("Input parameter: Either `true` to allow automatically deleting head branches when pull requests are merged, or `false` to prevent automatic deletion. **The authenticated user must be an organization owner to set this property to `true`.**")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the repository.")), + mcp.WithObject("custom_properties", mcp.Description("Input parameter: The custom properties for the new repository. The keys are the custom property names, and the values are the corresponding custom property values.")), + mcp.WithString("merge_commit_title", mcp.Description("Input parameter: Required when using `merge_commit_message`.\n\nThe default value for a merge commit title.\n\n- `PR_TITLE` - default to the pull request's title.\n- `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name).")), + mcp.WithString("gitignore_template", mcp.Description("Input parameter: Desired language or platform [.gitignore template](https://github.com/github/gitignore) to apply. Use the name of the template without the extension. For example, \"Haskell\".")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_or_update_custom_properties_values.go b/MCP/tools/repos/repos_create_or_update_custom_properties_values.go new file mode 100644 index 0000000..dfd6299 --- /dev/null +++ b/MCP/tools/repos/repos_create_or_update_custom_properties_values.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_or_update_custom_properties_valuesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/properties/values", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_or_update_custom_properties_valuesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_properties_values", + mcp.WithDescription("Create or update custom property values for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("properties", mcp.Required(), mcp.Description("Input parameter: A list of custom property names and associated values to apply to the repositories.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_or_update_custom_properties_valuesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_or_update_environment.go b/MCP/tools/repos/repos_create_or_update_environment.go new file mode 100644 index 0000000..5fcbd3d --- /dev/null +++ b/MCP/tools/repos/repos_create_or_update_environment.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_or_update_environmentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s", cfg.BaseURL, owner, repo, environment_name) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Environment + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_or_update_environmentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_environments_environment_name", + mcp.WithDescription("Create or update an environment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("wait_timer", mcp.Description("Input parameter: The amount of time to delay a job after the job is initially triggered. The time (in minutes) must be an integer between 0 and 43,200 (30 days).")), + mcp.WithObject("deployment_branch_policy", mcp.Description("Input parameter: The type of deployment branch policy for this environment. To allow all branches to deploy, set to `null`.")), + mcp.WithBoolean("prevent_self_review", mcp.Description("Input parameter: Whether or not a user who created the job is prevented from approving their own job.")), + mcp.WithArray("reviewers", mcp.Description("Input parameter: The people or teams that may review jobs that reference the environment. You can list up to six users or teams as reviewers. The reviewers must have at least read access to the repository. Only one of the required reviewers needs to approve the job for it to proceed.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_or_update_environmentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_or_update_file_contents.go b/MCP/tools/repos/repos_create_or_update_file_contents.go new file mode 100644 index 0000000..8445716 --- /dev/null +++ b/MCP/tools/repos/repos_create_or_update_file_contents.go @@ -0,0 +1,119 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_or_update_file_contentsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pathVal, ok := args["path"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: path"), nil + } + path, ok := pathVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: path"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/contents/%s", cfg.BaseURL, owner, repo, path) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_or_update_file_contentsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_contents_path", + mcp.WithDescription("Create or update file contents"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("path", mcp.Required(), mcp.Description("path parameter")), + mcp.WithObject("author", mcp.Description("Input parameter: The author of the file. Default: The `committer` or the authenticated user if you omit `committer`.")), + mcp.WithString("branch", mcp.Description("Input parameter: The branch name. Default: the repository’s default branch.")), + mcp.WithObject("committer", mcp.Description("Input parameter: The person that committed the file. Default: the authenticated user.")), + mcp.WithString("content", mcp.Required(), mcp.Description("Input parameter: The new file content, using Base64 encoding.")), + mcp.WithString("message", mcp.Required(), mcp.Description("Input parameter: The commit message.")), + mcp.WithString("sha", mcp.Description("Input parameter: **Required if you are updating a file**. The blob SHA of the file being replaced.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_or_update_file_contentsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_org_ruleset.go b/MCP/tools/repos/repos_create_org_ruleset.go new file mode 100644 index 0000000..2ad889b --- /dev/null +++ b/MCP/tools/repos/repos_create_org_ruleset.go @@ -0,0 +1,101 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_org_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/rulesets", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_org_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_rulesets", + mcp.WithDescription("Create an organization repository ruleset"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("enforcement", mcp.Required(), mcp.Description("Input parameter: The enforcement level of the ruleset. `evaluate` allows admins to test rules before enforcing them. Admins can view insights on the Rule Insights page (`evaluate` is only available with GitHub Enterprise).")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the ruleset.")), + mcp.WithArray("rules", mcp.Description("Input parameter: An array of rules within the ruleset.")), + mcp.WithString("target", mcp.Description("Input parameter: The target of the ruleset")), + mcp.WithArray("bypass_actors", mcp.Description("Input parameter: The actors that can bypass the rules in this ruleset")), + mcp.WithString("conditions", mcp.Description("Input parameter: Conditions for an organization ruleset.\nThe branch and tag rulesets conditions object should contain both `repository_name` and `ref_name` properties, or both `repository_id` and `ref_name` properties, or both `repository_property` and `ref_name` properties.\nThe push rulesets conditions object does not require the `ref_name` property.\nFor repository policy rulesets, the conditions object should only contain the `repository_name`, the `repository_id`, or the `repository_property`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_org_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_pages_deployment.go b/MCP/tools/repos/repos_create_pages_deployment.go new file mode 100644 index 0000000..dc92dfa --- /dev/null +++ b/MCP/tools/repos/repos_create_pages_deployment.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_pages_deploymentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/deployments", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_pages_deploymentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pages_deployments", + mcp.WithDescription("Create a GitHub Pages deployment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("artifact_id", mcp.Description("Input parameter: The ID of an artifact that contains the .zip or .tar of static assets to deploy. The artifact belongs to the repository. Either `artifact_id` or `artifact_url` are required.")), + mcp.WithString("artifact_url", mcp.Description("Input parameter: The URL of an artifact that contains the .zip or .tar of static assets to deploy. The artifact belongs to the repository. Either `artifact_id` or `artifact_url` are required.")), + mcp.WithString("environment", mcp.Description("Input parameter: The target environment for this GitHub Pages deployment.")), + mcp.WithString("oidc_token", mcp.Required(), mcp.Description("Input parameter: The OIDC token issued by GitHub Actions certifying the origin of the deployment.")), + mcp.WithString("pages_build_version", mcp.Required(), mcp.Description("Input parameter: A unique string that represents the version of the build for this deployment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_pages_deploymentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_pages_site.go b/MCP/tools/repos/repos_create_pages_site.go new file mode 100644 index 0000000..f99c253 --- /dev/null +++ b/MCP/tools/repos/repos_create_pages_site.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_pages_siteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Page + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_pages_siteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pages", + mcp.WithDescription("Create a GitHub Pages site"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("build_type", mcp.Description("Input parameter: The process in which the Page will be built. Possible values are `\"legacy\"` and `\"workflow\"`.")), + mcp.WithObject("source", mcp.Description("Input parameter: The source branch and directory used to publish your Pages site.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_pages_siteHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_release.go b/MCP/tools/repos/repos_create_release.go new file mode 100644 index 0000000..ac41852 --- /dev/null +++ b/MCP/tools/repos/repos_create_release.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Release + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_releases", + mcp.WithDescription("Create a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("make_latest", mcp.Description("Input parameter: Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Defaults to `true` for newly published releases. `legacy` specifies that the latest release should be determined based on the release creation date and higher semantic version.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the release.")), + mcp.WithString("discussion_category_name", mcp.Description("Input parameter: If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. For more information, see \"[Managing categories for discussions in your repository](https://docs.github.com/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository).\"")), + mcp.WithBoolean("draft", mcp.Description("Input parameter: `true` to create a draft (unpublished) release, `false` to create a published one.")), + mcp.WithString("target_commitish", mcp.Description("Input parameter: Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Unused if the Git tag already exists. Default: the repository's default branch.")), + mcp.WithBoolean("generate_release_notes", mcp.Description("Input parameter: Whether to automatically generate the name and body for this release. If `name` is specified, the specified name will be used; otherwise, a name will be automatically generated. If `body` is specified, the body will be pre-pended to the automatically generated notes.")), + mcp.WithBoolean("prerelease", mcp.Description("Input parameter: `true` to identify the release as a prerelease. `false` to identify the release as a full release.")), + mcp.WithString("tag_name", mcp.Required(), mcp.Description("Input parameter: The name of the tag.")), + mcp.WithString("body", mcp.Description("Input parameter: Text describing the contents of the tag.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_releaseHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_repo_ruleset.go b/MCP/tools/repos/repos_create_repo_ruleset.go new file mode 100644 index 0000000..b923ccc --- /dev/null +++ b/MCP/tools/repos/repos_create_repo_ruleset.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_repo_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_repo_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_rulesets", + mcp.WithDescription("Create a repository ruleset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("enforcement", mcp.Required(), mcp.Description("Input parameter: The enforcement level of the ruleset. `evaluate` allows admins to test rules before enforcing them. Admins can view insights on the Rule Insights page (`evaluate` is only available with GitHub Enterprise).")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the ruleset.")), + mcp.WithArray("rules", mcp.Description("Input parameter: An array of rules within the ruleset.")), + mcp.WithString("target", mcp.Description("Input parameter: The target of the ruleset")), + mcp.WithArray("bypass_actors", mcp.Description("Input parameter: The actors that can bypass the rules in this ruleset")), + mcp.WithObject("conditions", mcp.Description("Input parameter: Parameters for a repository ruleset ref name condition")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_repo_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_tag_protection.go b/MCP/tools/repos/repos_create_tag_protection.go new file mode 100644 index 0000000..b0b8e5b --- /dev/null +++ b/MCP/tools/repos/repos_create_tag_protection.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_tag_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/tags/protection", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_tag_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_tags_protection", + mcp.WithDescription("Closing down - Create a tag protection state for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("pattern", mcp.Required(), mcp.Description("Input parameter: An optional glob pattern to match against when enforcing tag protection.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_tag_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_using_template.go b/MCP/tools/repos/repos_create_using_template.go new file mode 100644 index 0000000..6ca7b0e --- /dev/null +++ b/MCP/tools/repos/repos_create_using_template.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_using_templateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + template_ownerVal, ok := args["template_owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: template_owner"), nil + } + template_owner, ok := template_ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: template_owner"), nil + } + template_repoVal, ok := args["template_repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: template_repo"), nil + } + template_repo, ok := template_repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: template_repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/generate", cfg.BaseURL, template_owner, template_repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_using_templateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_template_owner_template_repo_generate", + mcp.WithDescription("Create a repository using a template"), + mcp.WithString("template_owner", mcp.Required(), mcp.Description("The account owner of the template repository. The name is not case sensitive.")), + mcp.WithString("template_repo", mcp.Required(), mcp.Description("The name of the template repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("owner", mcp.Description("Input parameter: The organization or person who will own the new repository. To create a new repository in an organization, the authenticated user must be a member of the specified organization.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Either `true` to create a new private repository or `false` to create a new public one.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the new repository.")), + mcp.WithBoolean("include_all_branches", mcp.Description("Input parameter: Set to `true` to include the directory structure and files from all branches in the template repository, and not just the default branch. Default: `false`.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the new repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_using_templateHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_create_webhook.go b/MCP/tools/repos/repos_create_webhook.go new file mode 100644 index 0000000..076508e --- /dev/null +++ b/MCP/tools/repos/repos_create_webhook.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_create_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Hook + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_create_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_hooks", + mcp.WithDescription("Create a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("events", mcp.Description("Input parameter: Determines what [events](https://docs.github.com/webhooks/event-payloads) the hook is triggered for.")), + mcp.WithString("name", mcp.Description("Input parameter: Use `web` to create a webhook. Default: `web`. This parameter only accepts the value `web`.")), + mcp.WithBoolean("active", mcp.Description("Input parameter: Determines if notifications are sent when the webhook is triggered. Set to `true` to send notifications.")), + mcp.WithObject("config", mcp.Description("Input parameter: Key/value pairs to provide settings for this webhook.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_create_webhookHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_decline_invitation_for_authenticated_user.go b/MCP/tools/repos/repos_decline_invitation_for_authenticated_user.go new file mode 100644 index 0000000..f7f2e8f --- /dev/null +++ b/MCP/tools/repos/repos_decline_invitation_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_decline_invitation_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + invitation_idVal, ok := args["invitation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: invitation_id"), nil + } + invitation_id, ok := invitation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: invitation_id"), nil + } + url := fmt.Sprintf("%s/user/repository_invitations/%s", cfg.BaseURL, invitation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_decline_invitation_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_repository_invitations_invitation_id", + mcp.WithDescription("Decline a repository invitation"), + mcp.WithNumber("invitation_id", mcp.Required(), mcp.Description("The unique identifier of the invitation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_decline_invitation_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete.go b/MCP/tools/repos/repos_delete.go new file mode 100644 index 0000000..473465a --- /dev/null +++ b/MCP/tools/repos/repos_delete.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_deleteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_deleteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo", + mcp.WithDescription("Delete a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_deleteHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_access_restrictions.go b/MCP/tools/repos/repos_delete_access_restrictions.go new file mode 100644 index 0000000..33428bc --- /dev/null +++ b/MCP/tools/repos/repos_delete_access_restrictions.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_restrictions", + mcp.WithDescription("Delete access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_admin_branch_protection.go b/MCP/tools/repos/repos_delete_admin_branch_protection.go new file mode 100644 index 0000000..cb073d2 --- /dev/null +++ b/MCP/tools/repos/repos_delete_admin_branch_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_admin_branch_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/enforce_admins", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_admin_branch_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_enforce_admins", + mcp.WithDescription("Delete admin branch protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_admin_branch_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_an_environment.go b/MCP/tools/repos/repos_delete_an_environment.go new file mode 100644 index 0000000..9a537f1 --- /dev/null +++ b/MCP/tools/repos/repos_delete_an_environment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_an_environmentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s", cfg.BaseURL, owner, repo, environment_name) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_an_environmentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_environments_environment_name", + mcp.WithDescription("Delete an environment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_an_environmentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_autolink.go b/MCP/tools/repos/repos_delete_autolink.go new file mode 100644 index 0000000..0a2498e --- /dev/null +++ b/MCP/tools/repos/repos_delete_autolink.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_autolinkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + autolink_idVal, ok := args["autolink_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: autolink_id"), nil + } + autolink_id, ok := autolink_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: autolink_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/autolinks/%s", cfg.BaseURL, owner, repo, autolink_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_autolinkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_autolinks_autolink_id", + mcp.WithDescription("Delete an autolink reference from a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("autolink_id", mcp.Required(), mcp.Description("The unique identifier of the autolink.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_autolinkHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_branch_protection.go b/MCP/tools/repos/repos_delete_branch_protection.go new file mode 100644 index 0000000..d992ef0 --- /dev/null +++ b/MCP/tools/repos/repos_delete_branch_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_branch_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_branch_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection", + mcp.WithDescription("Delete branch protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_branch_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_commit_comment.go b/MCP/tools/repos/repos_delete_commit_comment.go new file mode 100644 index 0000000..3e58ba4 --- /dev/null +++ b/MCP/tools/repos/repos_delete_commit_comment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_comments_comment_id", + mcp.WithDescription("Delete a commit comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_commit_signature_protection.go b/MCP/tools/repos/repos_delete_commit_signature_protection.go new file mode 100644 index 0000000..518a507 --- /dev/null +++ b/MCP/tools/repos/repos_delete_commit_signature_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_commit_signature_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_signatures", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_commit_signature_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_required_signatures", + mcp.WithDescription("Delete commit signature protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_commit_signature_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_deploy_key.go b/MCP/tools/repos/repos_delete_deploy_key.go new file mode 100644 index 0000000..f34894f --- /dev/null +++ b/MCP/tools/repos/repos_delete_deploy_key.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_deploy_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + key_idVal, ok := args["key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: key_id"), nil + } + key_id, ok := key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: key_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/keys/%s", cfg.BaseURL, owner, repo, key_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_deploy_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_keys_key_id", + mcp.WithDescription("Delete a deploy key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("key_id", mcp.Required(), mcp.Description("The unique identifier of the key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_deploy_keyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_deployment.go b/MCP/tools/repos/repos_delete_deployment.go new file mode 100644 index 0000000..68cfc36 --- /dev/null +++ b/MCP/tools/repos/repos_delete_deployment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_deploymentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + deployment_idVal, ok := args["deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: deployment_id"), nil + } + deployment_id, ok := deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: deployment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments/%s", cfg.BaseURL, owner, repo, deployment_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_deploymentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_deployments_deployment_id", + mcp.WithDescription("Delete a deployment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("deployment_id", mcp.Required(), mcp.Description("deployment_id parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_deploymentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_deployment_branch_policy.go b/MCP/tools/repos/repos_delete_deployment_branch_policy.go new file mode 100644 index 0000000..0cc61bf --- /dev/null +++ b/MCP/tools/repos/repos_delete_deployment_branch_policy.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_deployment_branch_policyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + branch_policy_idVal, ok := args["branch_policy_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch_policy_id"), nil + } + branch_policy_id, ok := branch_policy_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch_policy_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment-branch-policies/%s", cfg.BaseURL, owner, repo, environment_name, branch_policy_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_deployment_branch_policyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_environments_environment_name_deployment-branch-policies_branch_policy_id", + mcp.WithDescription("Delete a deployment branch policy"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("branch_policy_id", mcp.Required(), mcp.Description("The unique identifier of the branch policy.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_deployment_branch_policyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_file.go b/MCP/tools/repos/repos_delete_file.go new file mode 100644 index 0000000..896bd85 --- /dev/null +++ b/MCP/tools/repos/repos_delete_file.go @@ -0,0 +1,118 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_fileHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pathVal, ok := args["path"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: path"), nil + } + path, ok := pathVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: path"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/contents/%s", cfg.BaseURL, owner, repo, path) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_fileTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_contents_path", + mcp.WithDescription("Delete a file"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("path", mcp.Required(), mcp.Description("path parameter")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The blob SHA of the file being deleted.")), + mcp.WithObject("author", mcp.Description("Input parameter: object containing information about the author.")), + mcp.WithString("branch", mcp.Description("Input parameter: The branch name. Default: the repository’s default branch")), + mcp.WithObject("committer", mcp.Description("Input parameter: object containing information about the committer.")), + mcp.WithString("message", mcp.Required(), mcp.Description("Input parameter: The commit message.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_fileHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_invitation.go b/MCP/tools/repos/repos_delete_invitation.go new file mode 100644 index 0000000..2668bfa --- /dev/null +++ b/MCP/tools/repos/repos_delete_invitation.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_invitationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + invitation_idVal, ok := args["invitation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: invitation_id"), nil + } + invitation_id, ok := invitation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: invitation_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/invitations/%s", cfg.BaseURL, owner, repo, invitation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_invitationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_invitations_invitation_id", + mcp.WithDescription("Delete a repository invitation"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("invitation_id", mcp.Required(), mcp.Description("The unique identifier of the invitation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_invitationHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_org_ruleset.go b/MCP/tools/repos/repos_delete_org_ruleset.go new file mode 100644 index 0000000..43ae38d --- /dev/null +++ b/MCP/tools/repos/repos_delete_org_ruleset.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_org_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/%s", cfg.BaseURL, org, ruleset_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_org_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_rulesets_ruleset_id", + mcp.WithDescription("Delete an organization repository ruleset"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_org_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_pages_site.go b/MCP/tools/repos/repos_delete_pages_site.go new file mode 100644 index 0000000..6610188 --- /dev/null +++ b/MCP/tools/repos/repos_delete_pages_site.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_pages_siteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_pages_siteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_pages", + mcp.WithDescription("Delete a GitHub Pages site"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_pages_siteHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_pull_request_review_protection.go b/MCP/tools/repos/repos_delete_pull_request_review_protection.go new file mode 100644 index 0000000..bb8dd20 --- /dev/null +++ b/MCP/tools/repos/repos_delete_pull_request_review_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_pull_request_review_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_pull_request_reviews", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_pull_request_review_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_required_pull_request_reviews", + mcp.WithDescription("Delete pull request review protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_pull_request_review_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_release.go b/MCP/tools/repos/repos_delete_release.go new file mode 100644 index 0000000..3e8a3ad --- /dev/null +++ b/MCP/tools/repos/repos_delete_release.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s", cfg.BaseURL, owner, repo, release_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_releases_release_id", + mcp.WithDescription("Delete a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_releaseHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_release_asset.go b/MCP/tools/repos/repos_delete_release_asset.go new file mode 100644 index 0000000..0c5e4db --- /dev/null +++ b/MCP/tools/repos/repos_delete_release_asset.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_release_assetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + asset_idVal, ok := args["asset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: asset_id"), nil + } + asset_id, ok := asset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: asset_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/assets/%s", cfg.BaseURL, owner, repo, asset_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_release_assetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_releases_assets_asset_id", + mcp.WithDescription("Delete a release asset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("asset_id", mcp.Required(), mcp.Description("The unique identifier of the asset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_release_assetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_repo_ruleset.go b/MCP/tools/repos/repos_delete_repo_ruleset.go new file mode 100644 index 0000000..7065db0 --- /dev/null +++ b/MCP/tools/repos/repos_delete_repo_ruleset.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_repo_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/%s", cfg.BaseURL, owner, repo, ruleset_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_repo_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_rulesets_ruleset_id", + mcp.WithDescription("Delete a repository ruleset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_repo_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_tag_protection.go b/MCP/tools/repos/repos_delete_tag_protection.go new file mode 100644 index 0000000..63e4a5e --- /dev/null +++ b/MCP/tools/repos/repos_delete_tag_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_tag_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + tag_protection_idVal, ok := args["tag_protection_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: tag_protection_id"), nil + } + tag_protection_id, ok := tag_protection_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: tag_protection_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/tags/protection/%s", cfg.BaseURL, owner, repo, tag_protection_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_tag_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_tags_protection_tag_protection_id", + mcp.WithDescription("Closing down - Delete a tag protection state for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("tag_protection_id", mcp.Required(), mcp.Description("The unique identifier of the tag protection.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_tag_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_delete_webhook.go b/MCP/tools/repos/repos_delete_webhook.go new file mode 100644 index 0000000..16832c3 --- /dev/null +++ b/MCP/tools/repos/repos_delete_webhook.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_delete_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_delete_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_hooks_hook_id", + mcp.WithDescription("Delete a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_delete_webhookHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_disable_automated_security_fixes.go b/MCP/tools/repos/repos_disable_automated_security_fixes.go new file mode 100644 index 0000000..e622cfb --- /dev/null +++ b/MCP/tools/repos/repos_disable_automated_security_fixes.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_disable_automated_security_fixesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/automated-security-fixes", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_disable_automated_security_fixesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_automated-security-fixes", + mcp.WithDescription("Disable Dependabot security updates"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_disable_automated_security_fixesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_disable_deployment_protection_rule.go b/MCP/tools/repos/repos_disable_deployment_protection_rule.go new file mode 100644 index 0000000..6e2f2a7 --- /dev/null +++ b/MCP/tools/repos/repos_disable_deployment_protection_rule.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_disable_deployment_protection_ruleHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + protection_rule_idVal, ok := args["protection_rule_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: protection_rule_id"), nil + } + protection_rule_id, ok := protection_rule_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: protection_rule_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment_protection_rules/%s", cfg.BaseURL, environment_name, repo, owner, protection_rule_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_disable_deployment_protection_ruleTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_environments_environment_name_deployment_protection_rules_protection_rule_id", + mcp.WithDescription("Disable a custom protection rule for an environment"), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithNumber("protection_rule_id", mcp.Required(), mcp.Description("The unique identifier of the protection rule.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_disable_deployment_protection_ruleHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_disable_private_vulnerability_reporting.go b/MCP/tools/repos/repos_disable_private_vulnerability_reporting.go new file mode 100644 index 0000000..993aa59 --- /dev/null +++ b/MCP/tools/repos/repos_disable_private_vulnerability_reporting.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_disable_private_vulnerability_reportingHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/private-vulnerability-reporting", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_disable_private_vulnerability_reportingTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_private-vulnerability-reporting", + mcp.WithDescription("Disable private vulnerability reporting for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_disable_private_vulnerability_reportingHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_disable_vulnerability_alerts.go b/MCP/tools/repos/repos_disable_vulnerability_alerts.go new file mode 100644 index 0000000..94d88ac --- /dev/null +++ b/MCP/tools/repos/repos_disable_vulnerability_alerts.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_disable_vulnerability_alertsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/vulnerability-alerts", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_disable_vulnerability_alertsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_vulnerability-alerts", + mcp.WithDescription("Disable vulnerability alerts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_disable_vulnerability_alertsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_download_tarball_archive.go b/MCP/tools/repos/repos_download_tarball_archive.go new file mode 100644 index 0000000..48e6dd0 --- /dev/null +++ b/MCP/tools/repos/repos_download_tarball_archive.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_download_tarball_archiveHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/tarball/%s", cfg.BaseURL, owner, repo, ref) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_download_tarball_archiveTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_tarball_ref", + mcp.WithDescription("Download a repository archive (tar)"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_download_tarball_archiveHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_download_zipball_archive.go b/MCP/tools/repos/repos_download_zipball_archive.go new file mode 100644 index 0000000..a5ded57 --- /dev/null +++ b/MCP/tools/repos/repos_download_zipball_archive.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_download_zipball_archiveHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/zipball/%s", cfg.BaseURL, owner, repo, ref) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_download_zipball_archiveTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_zipball_ref", + mcp.WithDescription("Download a repository archive (zip)"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_download_zipball_archiveHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_enable_automated_security_fixes.go b/MCP/tools/repos/repos_enable_automated_security_fixes.go new file mode 100644 index 0000000..aab17c9 --- /dev/null +++ b/MCP/tools/repos/repos_enable_automated_security_fixes.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_enable_automated_security_fixesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/automated-security-fixes", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_enable_automated_security_fixesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_automated-security-fixes", + mcp.WithDescription("Enable Dependabot security updates"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_enable_automated_security_fixesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_enable_private_vulnerability_reporting.go b/MCP/tools/repos/repos_enable_private_vulnerability_reporting.go new file mode 100644 index 0000000..e4c57c7 --- /dev/null +++ b/MCP/tools/repos/repos_enable_private_vulnerability_reporting.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_enable_private_vulnerability_reportingHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/private-vulnerability-reporting", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_enable_private_vulnerability_reportingTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_private-vulnerability-reporting", + mcp.WithDescription("Enable private vulnerability reporting for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_enable_private_vulnerability_reportingHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_enable_vulnerability_alerts.go b/MCP/tools/repos/repos_enable_vulnerability_alerts.go new file mode 100644 index 0000000..865e9f5 --- /dev/null +++ b/MCP/tools/repos/repos_enable_vulnerability_alerts.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_enable_vulnerability_alertsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/vulnerability-alerts", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_enable_vulnerability_alertsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_vulnerability-alerts", + mcp.WithDescription("Enable vulnerability alerts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_enable_vulnerability_alertsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_generate_release_notes.go b/MCP/tools/repos/repos_generate_release_notes.go new file mode 100644 index 0000000..152986a --- /dev/null +++ b/MCP/tools/repos/repos_generate_release_notes.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_generate_release_notesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/generate-notes", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_generate_release_notesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_releases_generate-notes", + mcp.WithDescription("Generate release notes content for a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("target_commitish", mcp.Description("Input parameter: Specifies the commitish value that will be the target for the release's tag. Required if the supplied tag_name does not reference an existing tag. Ignored if the tag_name already exists.")), + mcp.WithString("configuration_file_path", mcp.Description("Input parameter: Specifies a path to a file in the repository containing configuration settings used for generating the release notes. If unspecified, the configuration file located in the repository at '.github/release.yml' or '.github/release.yaml' will be used. If that is not present, the default configuration will be used.")), + mcp.WithString("previous_tag_name", mcp.Description("Input parameter: The name of the previous tag to use as the starting point for the release notes. Use to manually specify the range for the set of changes considered as part this release.")), + mcp.WithString("tag_name", mcp.Required(), mcp.Description("Input parameter: The tag name for the release. This can be an existing tag or a new one.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_generate_release_notesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get.go b/MCP/tools/repos/repos_get.go new file mode 100644 index 0000000..22ba787 --- /dev/null +++ b/MCP/tools/repos/repos_get.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_getHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_getTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo", + mcp.WithDescription("Get a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_getHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_access_restrictions.go b/MCP/tools/repos/repos_get_access_restrictions.go new file mode 100644 index 0000000..f8c71b2 --- /dev/null +++ b/MCP/tools/repos/repos_get_access_restrictions.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_restrictions", + mcp.WithDescription("Get access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_admin_branch_protection.go b/MCP/tools/repos/repos_get_admin_branch_protection.go new file mode 100644 index 0000000..c7990fe --- /dev/null +++ b/MCP/tools/repos/repos_get_admin_branch_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_admin_branch_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/enforce_admins", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_admin_branch_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_enforce_admins", + mcp.WithDescription("Get admin branch protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_admin_branch_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_all_deployment_protection_rules.go b/MCP/tools/repos/repos_get_all_deployment_protection_rules.go new file mode 100644 index 0000000..ab6964b --- /dev/null +++ b/MCP/tools/repos/repos_get_all_deployment_protection_rules.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_all_deployment_protection_rulesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment_protection_rules", cfg.BaseURL, environment_name, repo, owner) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_all_deployment_protection_rulesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_deployment_protection_rules", + mcp.WithDescription("Get all deployment protection rules for an environment"), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_all_deployment_protection_rulesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_all_environments.go b/MCP/tools/repos/repos_get_all_environments.go new file mode 100644 index 0000000..a488133 --- /dev/null +++ b/MCP/tools/repos/repos_get_all_environments.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_all_environmentsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/environments%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_all_environmentsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments", + mcp.WithDescription("List environments"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_all_environmentsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_all_status_check_contexts.go b/MCP/tools/repos/repos_get_all_status_check_contexts.go new file mode 100644 index 0000000..eae4e32 --- /dev/null +++ b/MCP/tools/repos/repos_get_all_status_check_contexts.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_all_status_check_contextsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks/contexts", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_all_status_check_contextsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_required_status_checks_contexts", + mcp.WithDescription("Get all status check contexts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_all_status_check_contextsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_all_topics.go b/MCP/tools/repos/repos_get_all_topics.go new file mode 100644 index 0000000..a07013a --- /dev/null +++ b/MCP/tools/repos/repos_get_all_topics.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_all_topicsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/topics%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Topic + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_all_topicsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_topics", + mcp.WithDescription("Get all repository topics"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_all_topicsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_apps_with_access_to_protected_branch.go b/MCP/tools/repos/repos_get_apps_with_access_to_protected_branch.go new file mode 100644 index 0000000..a278f1d --- /dev/null +++ b/MCP/tools/repos/repos_get_apps_with_access_to_protected_branch.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_apps_with_access_to_protected_branchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/apps", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Integration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_apps_with_access_to_protected_branchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_restrictions_apps", + mcp.WithDescription("Get apps with access to the protected branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_apps_with_access_to_protected_branchHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_autolink.go b/MCP/tools/repos/repos_get_autolink.go new file mode 100644 index 0000000..abe77db --- /dev/null +++ b/MCP/tools/repos/repos_get_autolink.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_autolinkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + autolink_idVal, ok := args["autolink_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: autolink_id"), nil + } + autolink_id, ok := autolink_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: autolink_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/autolinks/%s", cfg.BaseURL, owner, repo, autolink_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Autolink + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_autolinkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_autolinks_autolink_id", + mcp.WithDescription("Get an autolink reference of a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("autolink_id", mcp.Required(), mcp.Description("The unique identifier of the autolink.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_autolinkHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_branch.go b/MCP/tools/repos/repos_get_branch.go new file mode 100644 index 0000000..44ce001 --- /dev/null +++ b/MCP/tools/repos/repos_get_branch.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_branchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_branchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch", + mcp.WithDescription("Get a branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_branchHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_branch_protection.go b/MCP/tools/repos/repos_get_branch_protection.go new file mode 100644 index 0000000..7e9c4b0 --- /dev/null +++ b/MCP/tools/repos/repos_get_branch_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_branch_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_branch_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection", + mcp.WithDescription("Get branch protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_branch_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_branch_rules.go b/MCP/tools/repos/repos_get_branch_rules.go new file mode 100644 index 0000000..3d7e9f9 --- /dev/null +++ b/MCP/tools/repos/repos_get_branch_rules.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_branch_rulesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/rules/branches/%s%s", cfg.BaseURL, owner, repo, branch, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_branch_rulesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rules_branches_branch", + mcp.WithDescription("Get rules for a branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_branch_rulesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_clones.go b/MCP/tools/repos/repos_get_clones.go new file mode 100644 index 0000000..eaca93f --- /dev/null +++ b/MCP/tools/repos/repos_get_clones.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_clonesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/traffic/clones%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_clonesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_traffic_clones", + mcp.WithDescription("Get repository clones"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("per", mcp.Description("The time frame to display results for.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_clonesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_code_frequency_stats.go b/MCP/tools/repos/repos_get_code_frequency_stats.go new file mode 100644 index 0000000..c782b04 --- /dev/null +++ b/MCP/tools/repos/repos_get_code_frequency_stats.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_code_frequency_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/stats/code_frequency", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result [][]int + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_code_frequency_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_stats_code_frequency", + mcp.WithDescription("Get the weekly commit activity"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_code_frequency_statsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_collaborator_permission_level.go b/MCP/tools/repos/repos_get_collaborator_permission_level.go new file mode 100644 index 0000000..752d31d --- /dev/null +++ b/MCP/tools/repos/repos_get_collaborator_permission_level.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_collaborator_permission_levelHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/collaborators/%s/permission", cfg.BaseURL, owner, repo, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_collaborator_permission_levelTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_collaborators_username_permission", + mcp.WithDescription("Get repository permissions for a user"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_collaborator_permission_levelHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_combined_status_for_ref.go b/MCP/tools/repos/repos_get_combined_status_for_ref.go new file mode 100644 index 0000000..0e8cf04 --- /dev/null +++ b/MCP/tools/repos/repos_get_combined_status_for_ref.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_combined_status_for_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/status%s", cfg.BaseURL, owner, repo, ref, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_combined_status_for_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_ref_status", + mcp.WithDescription("Get the combined status for a specific reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The commit reference. Can be a commit SHA, branch name (`heads/BRANCH_NAME`), or tag name (`tags/TAG_NAME`). For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_combined_status_for_refHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_commit.go b/MCP/tools/repos/repos_get_commit.go new file mode 100644 index 0000000..994b9ac --- /dev/null +++ b/MCP/tools/repos/repos_get_commit.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_commitHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s%s", cfg.BaseURL, owner, repo, ref, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Commit + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_commitTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_ref", + mcp.WithDescription("Get a commit"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The commit reference. Can be a commit SHA, branch name (`heads/BRANCH_NAME`), or tag name (`tags/TAG_NAME`). For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_commitHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_commit_activity_stats.go b/MCP/tools/repos/repos_get_commit_activity_stats.go new file mode 100644 index 0000000..3f65c92 --- /dev/null +++ b/MCP/tools/repos/repos_get_commit_activity_stats.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_commit_activity_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/stats/commit_activity", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_commit_activity_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_stats_commit_activity", + mcp.WithDescription("Get the last year of commit activity"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_commit_activity_statsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_commit_comment.go b/MCP/tools/repos/repos_get_commit_comment.go new file mode 100644 index 0000000..ea1d35c --- /dev/null +++ b/MCP/tools/repos/repos_get_commit_comment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_comments_comment_id", + mcp.WithDescription("Get a commit comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_commit_signature_protection.go b/MCP/tools/repos/repos_get_commit_signature_protection.go new file mode 100644 index 0000000..af96556 --- /dev/null +++ b/MCP/tools/repos/repos_get_commit_signature_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_commit_signature_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_signatures", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_commit_signature_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_required_signatures", + mcp.WithDescription("Get commit signature protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_commit_signature_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_community_profile_metrics.go b/MCP/tools/repos/repos_get_community_profile_metrics.go new file mode 100644 index 0000000..e7deb85 --- /dev/null +++ b/MCP/tools/repos/repos_get_community_profile_metrics.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_community_profile_metricsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/community/profile", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_community_profile_metricsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_community_profile", + mcp.WithDescription("Get community profile metrics"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_community_profile_metricsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_content.go b/MCP/tools/repos/repos_get_content.go new file mode 100644 index 0000000..a5b70b4 --- /dev/null +++ b/MCP/tools/repos/repos_get_content.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_contentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pathVal, ok := args["path"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: path"), nil + } + path, ok := pathVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: path"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/contents/%s%s", cfg.BaseURL, owner, repo, path, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_contentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_contents_path", + mcp.WithDescription("Get repository content"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("path", mcp.Required(), mcp.Description("path parameter")), + mcp.WithString("ref", mcp.Description("The name of the commit/branch/tag. Default: the repository’s default branch.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_contentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_contributors_stats.go b/MCP/tools/repos/repos_get_contributors_stats.go new file mode 100644 index 0000000..4e8a591 --- /dev/null +++ b/MCP/tools/repos/repos_get_contributors_stats.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_contributors_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/stats/contributors", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_contributors_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_stats_contributors", + mcp.WithDescription("Get all contributor commit activity"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_contributors_statsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_custom_deployment_protection_rule.go b/MCP/tools/repos/repos_get_custom_deployment_protection_rule.go new file mode 100644 index 0000000..44904cb --- /dev/null +++ b/MCP/tools/repos/repos_get_custom_deployment_protection_rule.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_custom_deployment_protection_ruleHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + protection_rule_idVal, ok := args["protection_rule_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: protection_rule_id"), nil + } + protection_rule_id, ok := protection_rule_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: protection_rule_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment_protection_rules/%s", cfg.BaseURL, owner, repo, environment_name, protection_rule_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_custom_deployment_protection_ruleTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_deployment_protection_rules_protection_rule_id", + mcp.WithDescription("Get a custom deployment protection rule"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("protection_rule_id", mcp.Required(), mcp.Description("The unique identifier of the protection rule.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_custom_deployment_protection_ruleHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_custom_properties_values.go b/MCP/tools/repos/repos_get_custom_properties_values.go new file mode 100644 index 0000000..6a0e5aa --- /dev/null +++ b/MCP/tools/repos/repos_get_custom_properties_values.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_custom_properties_valuesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/properties/values", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_custom_properties_valuesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_properties_values", + mcp.WithDescription("Get all custom property values for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_custom_properties_valuesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_deploy_key.go b/MCP/tools/repos/repos_get_deploy_key.go new file mode 100644 index 0000000..ec40adf --- /dev/null +++ b/MCP/tools/repos/repos_get_deploy_key.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_deploy_keyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + key_idVal, ok := args["key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: key_id"), nil + } + key_id, ok := key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: key_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/keys/%s", cfg.BaseURL, owner, repo, key_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_deploy_keyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_keys_key_id", + mcp.WithDescription("Get a deploy key"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("key_id", mcp.Required(), mcp.Description("The unique identifier of the key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_deploy_keyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_deployment.go b/MCP/tools/repos/repos_get_deployment.go new file mode 100644 index 0000000..5cc24a0 --- /dev/null +++ b/MCP/tools/repos/repos_get_deployment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_deploymentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + deployment_idVal, ok := args["deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: deployment_id"), nil + } + deployment_id, ok := deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: deployment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments/%s", cfg.BaseURL, owner, repo, deployment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Deployment + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_deploymentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_deployments_deployment_id", + mcp.WithDescription("Get a deployment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("deployment_id", mcp.Required(), mcp.Description("deployment_id parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_deploymentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_deployment_branch_policy.go b/MCP/tools/repos/repos_get_deployment_branch_policy.go new file mode 100644 index 0000000..25a759d --- /dev/null +++ b/MCP/tools/repos/repos_get_deployment_branch_policy.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_deployment_branch_policyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + branch_policy_idVal, ok := args["branch_policy_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch_policy_id"), nil + } + branch_policy_id, ok := branch_policy_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch_policy_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment-branch-policies/%s", cfg.BaseURL, owner, repo, environment_name, branch_policy_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_deployment_branch_policyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_deployment-branch-policies_branch_policy_id", + mcp.WithDescription("Get a deployment branch policy"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("branch_policy_id", mcp.Required(), mcp.Description("The unique identifier of the branch policy.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_deployment_branch_policyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_deployment_status.go b/MCP/tools/repos/repos_get_deployment_status.go new file mode 100644 index 0000000..a519a47 --- /dev/null +++ b/MCP/tools/repos/repos_get_deployment_status.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_deployment_statusHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + deployment_idVal, ok := args["deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: deployment_id"), nil + } + deployment_id, ok := deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: deployment_id"), nil + } + status_idVal, ok := args["status_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: status_id"), nil + } + status_id, ok := status_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: status_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments/%s/statuses/%s", cfg.BaseURL, owner, repo, deployment_id, status_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_deployment_statusTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_deployments_deployment_id_statuses_status_id", + mcp.WithDescription("Get a deployment status"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("deployment_id", mcp.Required(), mcp.Description("deployment_id parameter")), + mcp.WithNumber("status_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_deployment_statusHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_environment.go b/MCP/tools/repos/repos_get_environment.go new file mode 100644 index 0000000..831ff1b --- /dev/null +++ b/MCP/tools/repos/repos_get_environment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_environmentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s", cfg.BaseURL, owner, repo, environment_name) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Environment + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_environmentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name", + mcp.WithDescription("Get an environment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_environmentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_latest_pages_build.go b/MCP/tools/repos/repos_get_latest_pages_build.go new file mode 100644 index 0000000..2d619f2 --- /dev/null +++ b/MCP/tools/repos/repos_get_latest_pages_build.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_latest_pages_buildHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/builds/latest", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_latest_pages_buildTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pages_builds_latest", + mcp.WithDescription("Get latest Pages build"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_latest_pages_buildHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_latest_release.go b/MCP/tools/repos/repos_get_latest_release.go new file mode 100644 index 0000000..169d1de --- /dev/null +++ b/MCP/tools/repos/repos_get_latest_release.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_latest_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/latest", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Release + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_latest_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases_latest", + mcp.WithDescription("Get the latest release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_latest_releaseHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_org_rule_suite.go b/MCP/tools/repos/repos_get_org_rule_suite.go new file mode 100644 index 0000000..6d5d426 --- /dev/null +++ b/MCP/tools/repos/repos_get_org_rule_suite.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_org_rule_suiteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + rule_suite_idVal, ok := args["rule_suite_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: rule_suite_id"), nil + } + rule_suite_id, ok := rule_suite_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: rule_suite_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/rule-suites/%s", cfg.BaseURL, org, rule_suite_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_org_rule_suiteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_rulesets_rule-suites_rule_suite_id", + mcp.WithDescription("Get an organization rule suite"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("rule_suite_id", mcp.Required(), mcp.Description("The unique identifier of the rule suite result.\nTo get this ID, you can use [GET /repos/{owner}/{repo}/rulesets/rule-suites](https://docs.github.com/rest/repos/rule-suites#list-repository-rule-suites)\nfor repositories and [GET /orgs/{org}/rulesets/rule-suites](https://docs.github.com/rest/orgs/rule-suites#list-organization-rule-suites)\nfor organizations.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_org_rule_suiteHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_org_rule_suites.go b/MCP/tools/repos/repos_get_org_rule_suites.go new file mode 100644 index 0000000..d8adb44 --- /dev/null +++ b/MCP/tools/repos/repos_get_org_rule_suites.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_org_rule_suitesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["repository_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("repository_name=%v", val)) + } + if val, ok := args["time_period"]; ok { + queryParams = append(queryParams, fmt.Sprintf("time_period=%v", val)) + } + if val, ok := args["actor_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("actor_name=%v", val)) + } + if val, ok := args["rule_suite_result"]; ok { + queryParams = append(queryParams, fmt.Sprintf("rule_suite_result=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/rule-suites%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_org_rule_suitesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_rulesets_rule-suites", + mcp.WithDescription("List organization rule suites"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Description("The name of the ref. Cannot contain wildcard characters. Optionally prefix with `refs/heads/` to limit to branches or `refs/tags/` to limit to tags. Omit the prefix to search across all refs. When specified, only rule evaluations triggered for this ref will be returned.")), + mcp.WithString("repository_name", mcp.Description("The name of the repository to filter on.")), + mcp.WithString("time_period", mcp.Description("The time period to filter by.\n\nFor example, `day` will filter for rule suites that occurred in the past 24 hours, and `week` will filter for rule suites that occurred in the past 7 days (168 hours).")), + mcp.WithString("actor_name", mcp.Description("The handle for the GitHub user account to filter on. When specified, only rule evaluations triggered by this actor will be returned.")), + mcp.WithString("rule_suite_result", mcp.Description("The rule suite results to filter on. When specified, only suites with this result will be returned.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_org_rule_suitesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_org_ruleset.go b/MCP/tools/repos/repos_get_org_ruleset.go new file mode 100644 index 0000000..a0c6481 --- /dev/null +++ b/MCP/tools/repos/repos_get_org_ruleset.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_org_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/%s", cfg.BaseURL, org, ruleset_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_org_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_rulesets_ruleset_id", + mcp.WithDescription("Get an organization repository ruleset"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_org_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_org_rulesets.go b/MCP/tools/repos/repos_get_org_rulesets.go new file mode 100644 index 0000000..f3c9524 --- /dev/null +++ b/MCP/tools/repos/repos_get_org_rulesets.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_org_rulesetsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["targets"]; ok { + queryParams = append(queryParams, fmt.Sprintf("targets=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/rulesets%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_org_rulesetsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_rulesets", + mcp.WithDescription("Get all organization repository rulesets"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("targets", mcp.Description("A comma-separated list of rule targets to filter by.\nIf provided, only rulesets that apply to the specified targets will be returned.\nFor example, `branch,tag,push`.\n")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_org_rulesetsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_pages.go b/MCP/tools/repos/repos_get_pages.go new file mode 100644 index 0000000..aad787c --- /dev/null +++ b/MCP/tools/repos/repos_get_pages.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_pagesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Page + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_pagesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pages", + mcp.WithDescription("Get a GitHub Pages site"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_pagesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_pages_build.go b/MCP/tools/repos/repos_get_pages_build.go new file mode 100644 index 0000000..a432a61 --- /dev/null +++ b/MCP/tools/repos/repos_get_pages_build.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_pages_buildHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + build_idVal, ok := args["build_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: build_id"), nil + } + build_id, ok := build_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: build_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/builds/%s", cfg.BaseURL, owner, repo, build_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_pages_buildTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pages_builds_build_id", + mcp.WithDescription("Get GitHub Pages build"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("build_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_pages_buildHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_pages_deployment.go b/MCP/tools/repos/repos_get_pages_deployment.go new file mode 100644 index 0000000..648c7cf --- /dev/null +++ b/MCP/tools/repos/repos_get_pages_deployment.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_pages_deploymentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + pages_deployment_idVal, ok := args["pages_deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: pages_deployment_id"), nil + } + pages_deployment_id, ok := pages_deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: pages_deployment_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/deployments/%s", cfg.BaseURL, owner, repo, pages_deployment_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_pages_deploymentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pages_deployments_pages_deployment_id", + mcp.WithDescription("Get the status of a GitHub Pages deployment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("pages_deployment_id", mcp.Required(), mcp.Description("The ID of the Pages deployment. You can also give the commit SHA of the deployment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_pages_deploymentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_pages_health_check.go b/MCP/tools/repos/repos_get_pages_health_check.go new file mode 100644 index 0000000..a0477c0 --- /dev/null +++ b/MCP/tools/repos/repos_get_pages_health_check.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_pages_health_checkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/health", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_pages_health_checkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pages_health", + mcp.WithDescription("Get a DNS health check for GitHub Pages"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_pages_health_checkHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_participation_stats.go b/MCP/tools/repos/repos_get_participation_stats.go new file mode 100644 index 0000000..be8a966 --- /dev/null +++ b/MCP/tools/repos/repos_get_participation_stats.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_participation_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/stats/participation", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_participation_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_stats_participation", + mcp.WithDescription("Get the weekly commit count"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_participation_statsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_pull_request_review_protection.go b/MCP/tools/repos/repos_get_pull_request_review_protection.go new file mode 100644 index 0000000..784e5ad --- /dev/null +++ b/MCP/tools/repos/repos_get_pull_request_review_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_pull_request_review_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_pull_request_reviews", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_pull_request_review_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_required_pull_request_reviews", + mcp.WithDescription("Get pull request review protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_pull_request_review_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_punch_card_stats.go b/MCP/tools/repos/repos_get_punch_card_stats.go new file mode 100644 index 0000000..6c0b087 --- /dev/null +++ b/MCP/tools/repos/repos_get_punch_card_stats.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_punch_card_statsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/stats/punch_card", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result [][]int + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_punch_card_statsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_stats_punch_card", + mcp.WithDescription("Get the hourly commit count for each day"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_punch_card_statsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_readme.go b/MCP/tools/repos/repos_get_readme.go new file mode 100644 index 0000000..bba5ac9 --- /dev/null +++ b/MCP/tools/repos/repos_get_readme.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_readmeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/readme%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_readmeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_readme", + mcp.WithDescription("Get a repository README"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Description("The name of the commit/branch/tag. Default: the repository’s default branch.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_readmeHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_readme_in_directory.go b/MCP/tools/repos/repos_get_readme_in_directory.go new file mode 100644 index 0000000..dfa1f31 --- /dev/null +++ b/MCP/tools/repos/repos_get_readme_in_directory.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_readme_in_directoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + dirVal, ok := args["dir"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: dir"), nil + } + dir, ok := dirVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: dir"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/readme/%s%s", cfg.BaseURL, owner, repo, dir, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_readme_in_directoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_readme_dir", + mcp.WithDescription("Get a repository README for a directory"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("dir", mcp.Required(), mcp.Description("The alternate path to look for a README file")), + mcp.WithString("ref", mcp.Description("The name of the commit/branch/tag. Default: the repository’s default branch.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_readme_in_directoryHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_release.go b/MCP/tools/repos/repos_get_release.go new file mode 100644 index 0000000..e2b84ab --- /dev/null +++ b/MCP/tools/repos/repos_get_release.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s", cfg.BaseURL, owner, repo, release_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Release + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases_release_id", + mcp.WithDescription("Get a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_releaseHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_release_asset.go b/MCP/tools/repos/repos_get_release_asset.go new file mode 100644 index 0000000..650606e --- /dev/null +++ b/MCP/tools/repos/repos_get_release_asset.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_release_assetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + asset_idVal, ok := args["asset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: asset_id"), nil + } + asset_id, ok := asset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: asset_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/assets/%s", cfg.BaseURL, owner, repo, asset_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_release_assetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases_assets_asset_id", + mcp.WithDescription("Get a release asset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("asset_id", mcp.Required(), mcp.Description("The unique identifier of the asset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_release_assetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_release_by_tag.go b/MCP/tools/repos/repos_get_release_by_tag.go new file mode 100644 index 0000000..aa71d6d --- /dev/null +++ b/MCP/tools/repos/repos_get_release_by_tag.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_release_by_tagHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + tagVal, ok := args["tag"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: tag"), nil + } + tag, ok := tagVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: tag"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/tags/%s", cfg.BaseURL, owner, repo, tag) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Release + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_release_by_tagTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases_tags_tag", + mcp.WithDescription("Get a release by tag name"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("tag", mcp.Required(), mcp.Description("tag parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_release_by_tagHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_repo_rule_suite.go b/MCP/tools/repos/repos_get_repo_rule_suite.go new file mode 100644 index 0000000..1d45649 --- /dev/null +++ b/MCP/tools/repos/repos_get_repo_rule_suite.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_repo_rule_suiteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + rule_suite_idVal, ok := args["rule_suite_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: rule_suite_id"), nil + } + rule_suite_id, ok := rule_suite_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: rule_suite_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/rule-suites/%s", cfg.BaseURL, owner, repo, rule_suite_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_repo_rule_suiteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rulesets_rule-suites_rule_suite_id", + mcp.WithDescription("Get a repository rule suite"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("rule_suite_id", mcp.Required(), mcp.Description("The unique identifier of the rule suite result.\nTo get this ID, you can use [GET /repos/{owner}/{repo}/rulesets/rule-suites](https://docs.github.com/rest/repos/rule-suites#list-repository-rule-suites)\nfor repositories and [GET /orgs/{org}/rulesets/rule-suites](https://docs.github.com/rest/orgs/rule-suites#list-organization-rule-suites)\nfor organizations.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_repo_rule_suiteHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_repo_rule_suites.go b/MCP/tools/repos/repos_get_repo_rule_suites.go new file mode 100644 index 0000000..0f17480 --- /dev/null +++ b/MCP/tools/repos/repos_get_repo_rule_suites.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_repo_rule_suitesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["time_period"]; ok { + queryParams = append(queryParams, fmt.Sprintf("time_period=%v", val)) + } + if val, ok := args["actor_name"]; ok { + queryParams = append(queryParams, fmt.Sprintf("actor_name=%v", val)) + } + if val, ok := args["rule_suite_result"]; ok { + queryParams = append(queryParams, fmt.Sprintf("rule_suite_result=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/rule-suites%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_repo_rule_suitesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rulesets_rule-suites", + mcp.WithDescription("List repository rule suites"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Description("The name of the ref. Cannot contain wildcard characters. Optionally prefix with `refs/heads/` to limit to branches or `refs/tags/` to limit to tags. Omit the prefix to search across all refs. When specified, only rule evaluations triggered for this ref will be returned.")), + mcp.WithString("time_period", mcp.Description("The time period to filter by.\n\nFor example, `day` will filter for rule suites that occurred in the past 24 hours, and `week` will filter for rule suites that occurred in the past 7 days (168 hours).")), + mcp.WithString("actor_name", mcp.Description("The handle for the GitHub user account to filter on. When specified, only rule evaluations triggered by this actor will be returned.")), + mcp.WithString("rule_suite_result", mcp.Description("The rule suite results to filter on. When specified, only suites with this result will be returned.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_repo_rule_suitesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_repo_ruleset.go b/MCP/tools/repos/repos_get_repo_ruleset.go new file mode 100644 index 0000000..35b6779 --- /dev/null +++ b/MCP/tools/repos/repos_get_repo_ruleset.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_repo_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["includes_parents"]; ok { + queryParams = append(queryParams, fmt.Sprintf("includes_parents=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/%s%s", cfg.BaseURL, owner, repo, ruleset_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_repo_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rulesets_ruleset_id", + mcp.WithDescription("Get a repository ruleset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + mcp.WithBoolean("includes_parents", mcp.Description("Include rulesets configured at higher levels that apply to this repository")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_repo_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_repo_ruleset_history.go b/MCP/tools/repos/repos_get_repo_ruleset_history.go new file mode 100644 index 0000000..f7232fb --- /dev/null +++ b/MCP/tools/repos/repos_get_repo_ruleset_history.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_repo_ruleset_historyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/%s/history%s", cfg.BaseURL, owner, repo, ruleset_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_repo_ruleset_historyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rulesets_ruleset_id_history", + mcp.WithDescription("Get repository ruleset history"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_repo_ruleset_historyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_repo_ruleset_version.go b/MCP/tools/repos/repos_get_repo_ruleset_version.go new file mode 100644 index 0000000..559f1bb --- /dev/null +++ b/MCP/tools/repos/repos_get_repo_ruleset_version.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_repo_ruleset_versionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + version_idVal, ok := args["version_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: version_id"), nil + } + version_id, ok := version_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: version_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/%s/history/%s", cfg.BaseURL, owner, repo, ruleset_id, version_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_repo_ruleset_versionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rulesets_ruleset_id_history_version_id", + mcp.WithDescription("Get repository ruleset version"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + mcp.WithNumber("version_id", mcp.Required(), mcp.Description("The ID of the version")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_repo_ruleset_versionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_repo_rulesets.go b/MCP/tools/repos/repos_get_repo_rulesets.go new file mode 100644 index 0000000..c763873 --- /dev/null +++ b/MCP/tools/repos/repos_get_repo_rulesets.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_repo_rulesetsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["includes_parents"]; ok { + queryParams = append(queryParams, fmt.Sprintf("includes_parents=%v", val)) + } + if val, ok := args["targets"]; ok { + queryParams = append(queryParams, fmt.Sprintf("targets=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_repo_rulesetsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_rulesets", + mcp.WithDescription("Get all repository rulesets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithBoolean("includes_parents", mcp.Description("Include rulesets configured at higher levels that apply to this repository")), + mcp.WithString("targets", mcp.Description("A comma-separated list of rule targets to filter by.\nIf provided, only rulesets that apply to the specified targets will be returned.\nFor example, `branch,tag,push`.\n")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_repo_rulesetsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_status_checks_protection.go b/MCP/tools/repos/repos_get_status_checks_protection.go new file mode 100644 index 0000000..5501870 --- /dev/null +++ b/MCP/tools/repos/repos_get_status_checks_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_status_checks_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_status_checks_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_required_status_checks", + mcp.WithDescription("Get status checks protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_status_checks_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_teams_with_access_to_protected_branch.go b/MCP/tools/repos/repos_get_teams_with_access_to_protected_branch.go new file mode 100644 index 0000000..a455cf3 --- /dev/null +++ b/MCP/tools/repos/repos_get_teams_with_access_to_protected_branch.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_teams_with_access_to_protected_branchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/teams", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_teams_with_access_to_protected_branchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_restrictions_teams", + mcp.WithDescription("Get teams with access to the protected branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_teams_with_access_to_protected_branchHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_top_paths.go b/MCP/tools/repos/repos_get_top_paths.go new file mode 100644 index 0000000..949dac5 --- /dev/null +++ b/MCP/tools/repos/repos_get_top_paths.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_top_pathsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/traffic/popular/paths", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_top_pathsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_traffic_popular_paths", + mcp.WithDescription("Get top referral paths"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_top_pathsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_top_referrers.go b/MCP/tools/repos/repos_get_top_referrers.go new file mode 100644 index 0000000..ecd561f --- /dev/null +++ b/MCP/tools/repos/repos_get_top_referrers.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_top_referrersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/traffic/popular/referrers", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_top_referrersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_traffic_popular_referrers", + mcp.WithDescription("Get top referral sources"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_top_referrersHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_users_with_access_to_protected_branch.go b/MCP/tools/repos/repos_get_users_with_access_to_protected_branch.go new file mode 100644 index 0000000..cae00fc --- /dev/null +++ b/MCP/tools/repos/repos_get_users_with_access_to_protected_branch.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_users_with_access_to_protected_branchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/users", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_users_with_access_to_protected_branchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches_branch_protection_restrictions_users", + mcp.WithDescription("Get users with access to the protected branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_users_with_access_to_protected_branchHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_views.go b/MCP/tools/repos/repos_get_views.go new file mode 100644 index 0000000..7a3cf0c --- /dev/null +++ b/MCP/tools/repos/repos_get_views.go @@ -0,0 +1,96 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_viewsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/traffic/views%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_viewsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_traffic_views", + mcp.WithDescription("Get page views"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("per", mcp.Description("The time frame to display results for.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_viewsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_webhook.go b/MCP/tools/repos/repos_get_webhook.go new file mode 100644 index 0000000..dafe052 --- /dev/null +++ b/MCP/tools/repos/repos_get_webhook.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Hook + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_hooks_hook_id", + mcp.WithDescription("Get a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_webhookHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_webhook_config_for_repo.go b/MCP/tools/repos/repos_get_webhook_config_for_repo.go new file mode 100644 index 0000000..9bbadcb --- /dev/null +++ b/MCP/tools/repos/repos_get_webhook_config_for_repo.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_webhook_config_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/config", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_webhook_config_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_hooks_hook_id_config", + mcp.WithDescription("Get a webhook configuration for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_webhook_config_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_get_webhook_delivery.go b/MCP/tools/repos/repos_get_webhook_delivery.go new file mode 100644 index 0000000..5d3a3f5 --- /dev/null +++ b/MCP/tools/repos/repos_get_webhook_delivery.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_get_webhook_deliveryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + delivery_idVal, ok := args["delivery_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: delivery_id"), nil + } + delivery_id, ok := delivery_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: delivery_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/deliveries/%s", cfg.BaseURL, owner, repo, hook_id, delivery_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_get_webhook_deliveryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_hooks_hook_id_deliveries_delivery_id", + mcp.WithDescription("Get a delivery for a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithNumber("delivery_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_get_webhook_deliveryHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_activities.go b/MCP/tools/repos/repos_list_activities.go new file mode 100644 index 0000000..a074088 --- /dev/null +++ b/MCP/tools/repos/repos_list_activities.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_activitiesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["actor"]; ok { + queryParams = append(queryParams, fmt.Sprintf("actor=%v", val)) + } + if val, ok := args["time_period"]; ok { + queryParams = append(queryParams, fmt.Sprintf("time_period=%v", val)) + } + if val, ok := args["activity_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("activity_type=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/activity%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Activity + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_activitiesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_activity", + mcp.WithDescription("List repository activities"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("ref", mcp.Description("The Git reference for the activities you want to list.\n\nThe `ref` for a branch can be formatted either as `refs/heads/BRANCH_NAME` or `BRANCH_NAME`, where `BRANCH_NAME` is the name of your branch.")), + mcp.WithString("actor", mcp.Description("The GitHub username to use to filter by the actor who performed the activity.")), + mcp.WithString("time_period", mcp.Description("The time period to filter by.\n\nFor example, `day` will filter for activity that occurred in the past 24 hours, and `week` will filter for activity that occurred in the past 7 days (168 hours).")), + mcp.WithString("activity_type", mcp.Description("The activity type to filter by.\n\nFor example, you can choose to filter by \"force_push\", to see all force pushes to the repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_activitiesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_attestations.go b/MCP/tools/repos/repos_list_attestations.go new file mode 100644 index 0000000..58db1da --- /dev/null +++ b/MCP/tools/repos/repos_list_attestations.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_attestationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + subject_digestVal, ok := args["subject_digest"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: subject_digest"), nil + } + subject_digest, ok := subject_digestVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: subject_digest"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["predicate_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("predicate_type=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/attestations/%s%s", cfg.BaseURL, owner, repo, subject_digest, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_attestationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_attestations_subject_digest", + mcp.WithDescription("List attestations"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("subject_digest", mcp.Required(), mcp.Description("The parameter should be set to the attestation's subject's SHA256 digest, in the form `sha256:HEX_DIGEST`.")), + mcp.WithString("predicate_type", mcp.Description("Optional filter for fetching attestations with a given predicate type.\nThis option accepts `provenance`, `sbom`, or freeform text for custom predicate types.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_attestationsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_autolinks.go b/MCP/tools/repos/repos_list_autolinks.go new file mode 100644 index 0000000..4940513 --- /dev/null +++ b/MCP/tools/repos/repos_list_autolinks.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_autolinksHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/autolinks", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Autolink + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_autolinksTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_autolinks", + mcp.WithDescription("Get all autolinks of a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_autolinksHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_branches.go b/MCP/tools/repos/repos_list_branches.go new file mode 100644 index 0000000..db29484 --- /dev/null +++ b/MCP/tools/repos/repos_list_branches.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_branchesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["protected"]; ok { + queryParams = append(queryParams, fmt.Sprintf("protected=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/branches%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_branchesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_branches", + mcp.WithDescription("List branches"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("protected", mcp.Description("Setting to `true` returns only branches protected by branch protections or rulesets. When set to `false`, only unprotected branches are returned. Omitting this parameter returns all branches.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_branchesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_branches_for_head_commit.go b/MCP/tools/repos/repos_list_branches_for_head_commit.go new file mode 100644 index 0000000..103faec --- /dev/null +++ b/MCP/tools/repos/repos_list_branches_for_head_commit.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_branches_for_head_commitHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + commit_shaVal, ok := args["commit_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: commit_sha"), nil + } + commit_sha, ok := commit_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: commit_sha"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/branches-where-head", cfg.BaseURL, owner, repo, commit_sha) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_branches_for_head_commitTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_commit_sha_branches-where-head", + mcp.WithDescription("List branches for HEAD commit"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("commit_sha", mcp.Required(), mcp.Description("The SHA of the commit.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_branches_for_head_commitHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_collaborators.go b/MCP/tools/repos/repos_list_collaborators.go new file mode 100644 index 0000000..23ec789 --- /dev/null +++ b/MCP/tools/repos/repos_list_collaborators.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_collaboratorsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["affiliation"]; ok { + queryParams = append(queryParams, fmt.Sprintf("affiliation=%v", val)) + } + if val, ok := args["permission"]; ok { + queryParams = append(queryParams, fmt.Sprintf("permission=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/collaborators%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Collaborator + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_collaboratorsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_collaborators", + mcp.WithDescription("List repository collaborators"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("affiliation", mcp.Description("Filter collaborators returned by their affiliation. `outside` means all outside collaborators of an organization-owned repository. `direct` means all collaborators with permissions to an organization-owned repository, regardless of organization membership status. `all` means all collaborators the authenticated user can see.")), + mcp.WithString("permission", mcp.Description("Filter collaborators by the permissions they have on the repository. If not specified, all collaborators will be returned.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_collaboratorsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_comments_for_commit.go b/MCP/tools/repos/repos_list_comments_for_commit.go new file mode 100644 index 0000000..19a8294 --- /dev/null +++ b/MCP/tools/repos/repos_list_comments_for_commit.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_comments_for_commitHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + commit_shaVal, ok := args["commit_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: commit_sha"), nil + } + commit_sha, ok := commit_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: commit_sha"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/comments%s", cfg.BaseURL, owner, repo, commit_sha, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_comments_for_commitTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_commit_sha_comments", + mcp.WithDescription("List commit comments"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("commit_sha", mcp.Required(), mcp.Description("The SHA of the commit.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_comments_for_commitHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_commit_comments_for_repo.go b/MCP/tools/repos/repos_list_commit_comments_for_repo.go new file mode 100644 index 0000000..63f0188 --- /dev/null +++ b/MCP/tools/repos/repos_list_commit_comments_for_repo.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_commit_comments_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/comments%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_commit_comments_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_comments", + mcp.WithDescription("List commit comments for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_commit_comments_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_commit_statuses_for_ref.go b/MCP/tools/repos/repos_list_commit_statuses_for_ref.go new file mode 100644 index 0000000..71b2731 --- /dev/null +++ b/MCP/tools/repos/repos_list_commit_statuses_for_ref.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_commit_statuses_for_refHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + refVal, ok := args["ref"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ref"), nil + } + ref, ok := refVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ref"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/statuses%s", cfg.BaseURL, owner, repo, ref, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Status + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_commit_statuses_for_refTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_ref_statuses", + mcp.WithDescription("List commit statuses for a reference"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ref", mcp.Required(), mcp.Description("The commit reference. Can be a commit SHA, branch name (`heads/BRANCH_NAME`), or tag name (`tags/TAG_NAME`). For more information, see \"[Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References)\" in the Git documentation.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_commit_statuses_for_refHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_commits.go b/MCP/tools/repos/repos_list_commits.go new file mode 100644 index 0000000..3ae5568 --- /dev/null +++ b/MCP/tools/repos/repos_list_commits.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_commitsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sha"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sha=%v", val)) + } + if val, ok := args["path"]; ok { + queryParams = append(queryParams, fmt.Sprintf("path=%v", val)) + } + if val, ok := args["author"]; ok { + queryParams = append(queryParams, fmt.Sprintf("author=%v", val)) + } + if val, ok := args["committer"]; ok { + queryParams = append(queryParams, fmt.Sprintf("committer=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["until"]; ok { + queryParams = append(queryParams, fmt.Sprintf("until=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Commit + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_commitsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits", + mcp.WithDescription("List commits"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sha", mcp.Description("SHA or branch to start listing commits from. Default: the repository’s default branch (usually `main`).")), + mcp.WithString("path", mcp.Description("Only commits containing this file path will be returned.")), + mcp.WithString("author", mcp.Description("GitHub username or email address to use to filter by commit author.")), + mcp.WithString("committer", mcp.Description("GitHub username or email address to use to filter by commit committer.")), + mcp.WithString("since", mcp.Description("Only show results that were last updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`. Due to limitations of Git, timestamps must be between 1970-01-01 and 2099-12-31 (inclusive) or unexpected results may be returned.")), + mcp.WithString("until", mcp.Description("Only commits before this date will be returned. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`. Due to limitations of Git, timestamps must be between 1970-01-01 and 2099-12-31 (inclusive) or unexpected results may be returned.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_commitsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_contributors.go b/MCP/tools/repos/repos_list_contributors.go new file mode 100644 index 0000000..9392f75 --- /dev/null +++ b/MCP/tools/repos/repos_list_contributors.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_contributorsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["anon"]; ok { + queryParams = append(queryParams, fmt.Sprintf("anon=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/contributors%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Contributor + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_contributorsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_contributors", + mcp.WithDescription("List repository contributors"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("anon", mcp.Description("Set to `1` or `true` to include anonymous contributors in results.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_contributorsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_custom_deployment_rule_integrations.go b/MCP/tools/repos/repos_list_custom_deployment_rule_integrations.go new file mode 100644 index 0000000..e4e180a --- /dev/null +++ b/MCP/tools/repos/repos_list_custom_deployment_rule_integrations.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_custom_deployment_rule_integrationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment_protection_rules/apps%s", cfg.BaseURL, environment_name, repo, owner, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_custom_deployment_rule_integrationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_deployment_protection_rules_apps", + mcp.WithDescription("List custom deployment rule integrations available for an environment"), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_custom_deployment_rule_integrationsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_deploy_keys.go b/MCP/tools/repos/repos_list_deploy_keys.go new file mode 100644 index 0000000..cef355b --- /dev/null +++ b/MCP/tools/repos/repos_list_deploy_keys.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_deploy_keysHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/keys%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_deploy_keysTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_keys", + mcp.WithDescription("List deploy keys"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_deploy_keysHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_deployment_branch_policies.go b/MCP/tools/repos/repos_list_deployment_branch_policies.go new file mode 100644 index 0000000..3475d35 --- /dev/null +++ b/MCP/tools/repos/repos_list_deployment_branch_policies.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_deployment_branch_policiesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment-branch-policies%s", cfg.BaseURL, owner, repo, environment_name, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_deployment_branch_policiesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_environments_environment_name_deployment-branch-policies", + mcp.WithDescription("List deployment branch policies"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_deployment_branch_policiesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_deployment_statuses.go b/MCP/tools/repos/repos_list_deployment_statuses.go new file mode 100644 index 0000000..b7f8505 --- /dev/null +++ b/MCP/tools/repos/repos_list_deployment_statuses.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_deployment_statusesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + deployment_idVal, ok := args["deployment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: deployment_id"), nil + } + deployment_id, ok := deployment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: deployment_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments/%s/statuses%s", cfg.BaseURL, owner, repo, deployment_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_deployment_statusesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_deployments_deployment_id_statuses", + mcp.WithDescription("List deployment statuses"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("deployment_id", mcp.Required(), mcp.Description("deployment_id parameter")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_deployment_statusesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_deployments.go b/MCP/tools/repos/repos_list_deployments.go new file mode 100644 index 0000000..8a89588 --- /dev/null +++ b/MCP/tools/repos/repos_list_deployments.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_deploymentsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sha"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sha=%v", val)) + } + if val, ok := args["ref"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ref=%v", val)) + } + if val, ok := args["task"]; ok { + queryParams = append(queryParams, fmt.Sprintf("task=%v", val)) + } + if val, ok := args["environment"]; ok { + queryParams = append(queryParams, fmt.Sprintf("environment=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/deployments%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Deployment + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_deploymentsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_deployments", + mcp.WithDescription("List deployments"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sha", mcp.Description("The SHA recorded at creation time.")), + mcp.WithString("ref", mcp.Description("The name of the ref. This can be a branch, tag, or SHA.")), + mcp.WithString("task", mcp.Description("The name of the task for the deployment (e.g., `deploy` or `deploy:migrations`).")), + mcp.WithString("environment", mcp.Description("The name of the environment that was deployed to (e.g., `staging` or `production`).")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_deploymentsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_for_authenticated_user.go b/MCP/tools/repos/repos_list_for_authenticated_user.go new file mode 100644 index 0000000..ffd6d32 --- /dev/null +++ b/MCP/tools/repos/repos_list_for_authenticated_user.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["visibility"]; ok { + queryParams = append(queryParams, fmt.Sprintf("visibility=%v", val)) + } + if val, ok := args["affiliation"]; ok { + queryParams = append(queryParams, fmt.Sprintf("affiliation=%v", val)) + } + if val, ok := args["type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("type=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/repos%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Repository + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_repos", + mcp.WithDescription("List repositories for the authenticated user"), + mcp.WithString("visibility", mcp.Description("Limit results to repositories with the specified visibility.")), + mcp.WithString("affiliation", mcp.Description("Comma-separated list of values. Can include: \n * `owner`: Repositories that are owned by the authenticated user. \n * `collaborator`: Repositories that the user has been added to as a collaborator. \n * `organization_member`: Repositories that the user has access to through being a member of an organization. This includes every repository on every team that the user is on.")), + mcp.WithString("type", mcp.Description("Limit results to repositories of the specified type. Will cause a `422` error if used in the same request as **visibility** or **affiliation**.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("The order to sort by. Default: `asc` when using `full_name`, otherwise `desc`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("since", mcp.Description("Only show repositories updated after the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + mcp.WithString("before", mcp.Description("Only show repositories updated before the given time. This is a timestamp in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format: `YYYY-MM-DDTHH:MM:SSZ`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_for_org.go b/MCP/tools/repos/repos_list_for_org.go new file mode 100644 index 0000000..1fe5097 --- /dev/null +++ b/MCP/tools/repos/repos_list_for_org.go @@ -0,0 +1,103 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("type=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/repos%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_repos", + mcp.WithDescription("List organization repositories"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("type", mcp.Description("Specifies the types of repositories you want returned.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("The order to sort by. Default: `asc` when using `full_name`, otherwise `desc`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_for_user.go b/MCP/tools/repos/repos_list_for_user.go new file mode 100644 index 0000000..b5e7776 --- /dev/null +++ b/MCP/tools/repos/repos_list_for_user.go @@ -0,0 +1,103 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("type=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/repos%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_repos", + mcp.WithDescription("List repositories for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("type", mcp.Description("Limit results to repositories of the specified type.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("direction", mcp.Description("The order to sort by. Default: `asc` when using `full_name`, otherwise `desc`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_for_userHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_forks.go b/MCP/tools/repos/repos_list_forks.go new file mode 100644 index 0000000..c0dc3e2 --- /dev/null +++ b/MCP/tools/repos/repos_list_forks.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_forksHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/forks%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_forksTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_forks", + mcp.WithDescription("List forks"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("sort", mcp.Description("The sort order. `stargazers` will sort by star count.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_forksHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_invitations.go b/MCP/tools/repos/repos_list_invitations.go new file mode 100644 index 0000000..f3443c1 --- /dev/null +++ b/MCP/tools/repos/repos_list_invitations.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_invitationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/invitations%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_invitationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_invitations", + mcp.WithDescription("List repository invitations"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_invitationsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_invitations_for_authenticated_user.go b/MCP/tools/repos/repos_list_invitations_for_authenticated_user.go new file mode 100644 index 0000000..5eff5ca --- /dev/null +++ b/MCP/tools/repos/repos_list_invitations_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_invitations_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/repository_invitations%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_invitations_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_repository_invitations", + mcp.WithDescription("List repository invitations for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_invitations_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_languages.go b/MCP/tools/repos/repos_list_languages.go new file mode 100644 index 0000000..ae16d42 --- /dev/null +++ b/MCP/tools/repos/repos_list_languages.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_languagesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/languages", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Language + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_languagesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_languages", + mcp.WithDescription("List repository languages"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_languagesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_pages_builds.go b/MCP/tools/repos/repos_list_pages_builds.go new file mode 100644 index 0000000..bccacf6 --- /dev/null +++ b/MCP/tools/repos/repos_list_pages_builds.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_pages_buildsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/builds%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_pages_buildsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_pages_builds", + mcp.WithDescription("List GitHub Pages builds"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_pages_buildsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_public.go b/MCP/tools/repos/repos_list_public.go new file mode 100644 index 0000000..21f7294 --- /dev/null +++ b/MCP/tools/repos/repos_list_public.go @@ -0,0 +1,78 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_publicHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repositories%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_publicTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repositories", + mcp.WithDescription("List public repositories"), + mcp.WithNumber("since", mcp.Description("A repository ID. Only return repositories with an ID greater than this ID.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_publicHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_pull_requests_associated_with_commit.go b/MCP/tools/repos/repos_list_pull_requests_associated_with_commit.go new file mode 100644 index 0000000..250e0d6 --- /dev/null +++ b/MCP/tools/repos/repos_list_pull_requests_associated_with_commit.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_pull_requests_associated_with_commitHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + commit_shaVal, ok := args["commit_sha"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: commit_sha"), nil + } + commit_sha, ok := commit_shaVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: commit_sha"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/commits/%s/pulls%s", cfg.BaseURL, owner, repo, commit_sha, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_pull_requests_associated_with_commitTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_commits_commit_sha_pulls", + mcp.WithDescription("List pull requests associated with a commit"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("commit_sha", mcp.Required(), mcp.Description("The SHA of the commit.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_pull_requests_associated_with_commitHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_release_assets.go b/MCP/tools/repos/repos_list_release_assets.go new file mode 100644 index 0000000..f08c85a --- /dev/null +++ b/MCP/tools/repos/repos_list_release_assets.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_release_assetsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s/assets%s", cfg.BaseURL, owner, repo, release_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_release_assetsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases_release_id_assets", + mcp.WithDescription("List release assets"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_release_assetsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_releases.go b/MCP/tools/repos/repos_list_releases.go new file mode 100644 index 0000000..6592d5d --- /dev/null +++ b/MCP/tools/repos/repos_list_releases.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_releasesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/releases%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Release + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_releasesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_releases", + mcp.WithDescription("List releases"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_releasesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_tag_protection.go b/MCP/tools/repos/repos_list_tag_protection.go new file mode 100644 index 0000000..ff15e09 --- /dev/null +++ b/MCP/tools/repos/repos_list_tag_protection.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_tag_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/tags/protection", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_tag_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_tags_protection", + mcp.WithDescription("Closing down - List tag protection states for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_tag_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_tags.go b/MCP/tools/repos/repos_list_tags.go new file mode 100644 index 0000000..286bb08 --- /dev/null +++ b/MCP/tools/repos/repos_list_tags.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_tagsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/tags%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Tag + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_tagsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_tags", + mcp.WithDescription("List repository tags"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_tagsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_teams.go b/MCP/tools/repos/repos_list_teams.go new file mode 100644 index 0000000..ec3e1ad --- /dev/null +++ b/MCP/tools/repos/repos_list_teams.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_teamsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/teams%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_teamsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_teams", + mcp.WithDescription("List repository teams"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_teamsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_webhook_deliveries.go b/MCP/tools/repos/repos_list_webhook_deliveries.go new file mode 100644 index 0000000..a701a5b --- /dev/null +++ b/MCP/tools/repos/repos_list_webhook_deliveries.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_webhook_deliveriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["cursor"]; ok { + queryParams = append(queryParams, fmt.Sprintf("cursor=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/deliveries%s", cfg.BaseURL, owner, repo, hook_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_webhook_deliveriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_hooks_hook_id_deliveries", + mcp.WithDescription("List deliveries for a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("cursor", mcp.Description("Used for pagination: the starting delivery from which the page of deliveries is fetched. Refer to the `link` header for the next and previous page cursors.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_webhook_deliveriesHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_list_webhooks.go b/MCP/tools/repos/repos_list_webhooks.go new file mode 100644 index 0000000..a5e8eb1 --- /dev/null +++ b/MCP/tools/repos/repos_list_webhooks.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_list_webhooksHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Hook + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_list_webhooksTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_hooks", + mcp.WithDescription("List repository webhooks"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_list_webhooksHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_merge.go b/MCP/tools/repos/repos_merge.go new file mode 100644 index 0000000..b7d7408 --- /dev/null +++ b/MCP/tools/repos/repos_merge.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_mergeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/merges", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Commit + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_mergeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_merges", + mcp.WithDescription("Merge a branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("base", mcp.Required(), mcp.Description("Input parameter: The name of the base branch that the head will be merged into.")), + mcp.WithString("commit_message", mcp.Description("Input parameter: Commit message to use for the merge commit. If omitted, a default message will be used.")), + mcp.WithString("head", mcp.Required(), mcp.Description("Input parameter: The head to merge. This can be a branch name or a commit SHA1.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_mergeHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_merge_upstream.go b/MCP/tools/repos/repos_merge_upstream.go new file mode 100644 index 0000000..d107d28 --- /dev/null +++ b/MCP/tools/repos/repos_merge_upstream.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_merge_upstreamHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/merge-upstream", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_merge_upstreamTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_merge-upstream", + mcp.WithDescription("Sync a fork branch with the upstream repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("Input parameter: The name of the branch which should be updated to match upstream.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_merge_upstreamHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_ping_webhook.go b/MCP/tools/repos/repos_ping_webhook.go new file mode 100644 index 0000000..fe70ef3 --- /dev/null +++ b/MCP/tools/repos/repos_ping_webhook.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_ping_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/pings", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_ping_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_hooks_hook_id_pings", + mcp.WithDescription("Ping a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_ping_webhookHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_redeliver_webhook_delivery.go b/MCP/tools/repos/repos_redeliver_webhook_delivery.go new file mode 100644 index 0000000..3d7fa67 --- /dev/null +++ b/MCP/tools/repos/repos_redeliver_webhook_delivery.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_redeliver_webhook_deliveryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + delivery_idVal, ok := args["delivery_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: delivery_id"), nil + } + delivery_id, ok := delivery_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: delivery_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/deliveries/%s/attempts", cfg.BaseURL, owner, repo, hook_id, delivery_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_redeliver_webhook_deliveryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_hooks_hook_id_deliveries_delivery_id_attempts", + mcp.WithDescription("Redeliver a delivery for a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithNumber("delivery_id", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_redeliver_webhook_deliveryHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_remove_app_access_restrictions.go b/MCP/tools/repos/repos_remove_app_access_restrictions.go new file mode 100644 index 0000000..0a6907c --- /dev/null +++ b/MCP/tools/repos/repos_remove_app_access_restrictions.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_remove_app_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/apps", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Integration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_remove_app_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_restrictions_apps", + mcp.WithDescription("Remove app access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("apps", mcp.Required(), mcp.Description("Input parameter: The GitHub Apps that have push access to this branch. Use the slugified version of the app name. **Note**: The list of users, apps, and teams in total is limited to 100 items.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_remove_app_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_remove_collaborator.go b/MCP/tools/repos/repos_remove_collaborator.go new file mode 100644 index 0000000..05f2a57 --- /dev/null +++ b/MCP/tools/repos/repos_remove_collaborator.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_remove_collaboratorHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/collaborators/%s", cfg.BaseURL, owner, repo, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_remove_collaboratorTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_collaborators_username", + mcp.WithDescription("Remove a repository collaborator"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_remove_collaboratorHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_remove_status_check_contexts.go b/MCP/tools/repos/repos_remove_status_check_contexts.go new file mode 100644 index 0000000..c33b338 --- /dev/null +++ b/MCP/tools/repos/repos_remove_status_check_contexts.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_remove_status_check_contextsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks/contexts", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_remove_status_check_contextsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_required_status_checks_contexts", + mcp.WithDescription("Remove status check contexts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_remove_status_check_contextsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_remove_status_check_protection.go b/MCP/tools/repos/repos_remove_status_check_protection.go new file mode 100644 index 0000000..1cab150 --- /dev/null +++ b/MCP/tools/repos/repos_remove_status_check_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_remove_status_check_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_remove_status_check_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_required_status_checks", + mcp.WithDescription("Remove status check protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_remove_status_check_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_remove_team_access_restrictions.go b/MCP/tools/repos/repos_remove_team_access_restrictions.go new file mode 100644 index 0000000..dac0972 --- /dev/null +++ b/MCP/tools/repos/repos_remove_team_access_restrictions.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_remove_team_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/teams", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_remove_team_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_restrictions_teams", + mcp.WithDescription("Remove team access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_remove_team_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_remove_user_access_restrictions.go b/MCP/tools/repos/repos_remove_user_access_restrictions.go new file mode 100644 index 0000000..c0c1286 --- /dev/null +++ b/MCP/tools/repos/repos_remove_user_access_restrictions.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_remove_user_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/users", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_remove_user_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_repos_owner_repo_branches_branch_protection_restrictions_users", + mcp.WithDescription("Remove user access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("users", mcp.Required(), mcp.Description("Input parameter: The username for users")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_remove_user_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_rename_branch.go b/MCP/tools/repos/repos_rename_branch.go new file mode 100644 index 0000000..fd06c2c --- /dev/null +++ b/MCP/tools/repos/repos_rename_branch.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_rename_branchHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/rename", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_rename_branchTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_rename", + mcp.WithDescription("Rename a branch"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithString("new_name", mcp.Required(), mcp.Description("Input parameter: The new name of the branch.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_rename_branchHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_replace_all_topics.go b/MCP/tools/repos/repos_replace_all_topics.go new file mode 100644 index 0000000..6150e02 --- /dev/null +++ b/MCP/tools/repos/repos_replace_all_topics.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_replace_all_topicsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/topics", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Topic + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_replace_all_topicsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_topics", + mcp.WithDescription("Replace all repository topics"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("names", mcp.Required(), mcp.Description("Input parameter: An array of topics to add to the repository. Pass one or more topics to _replace_ the set of existing topics. Send an empty array (`[]`) to clear all topics from the repository. **Note:** Topic `names` will be saved as lowercase.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_replace_all_topicsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_request_pages_build.go b/MCP/tools/repos/repos_request_pages_build.go new file mode 100644 index 0000000..225987c --- /dev/null +++ b/MCP/tools/repos/repos_request_pages_build.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_request_pages_buildHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages/builds", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_request_pages_buildTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_pages_builds", + mcp.WithDescription("Request a GitHub Pages build"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_request_pages_buildHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_set_admin_branch_protection.go b/MCP/tools/repos/repos_set_admin_branch_protection.go new file mode 100644 index 0000000..516a06a --- /dev/null +++ b/MCP/tools/repos/repos_set_admin_branch_protection.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_set_admin_branch_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/enforce_admins", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_set_admin_branch_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_branches_branch_protection_enforce_admins", + mcp.WithDescription("Set admin branch protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_set_admin_branch_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_set_app_access_restrictions.go b/MCP/tools/repos/repos_set_app_access_restrictions.go new file mode 100644 index 0000000..de973a5 --- /dev/null +++ b/MCP/tools/repos/repos_set_app_access_restrictions.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_set_app_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/apps", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Integration + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_set_app_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_branches_branch_protection_restrictions_apps", + mcp.WithDescription("Set app access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("apps", mcp.Required(), mcp.Description("Input parameter: The GitHub Apps that have push access to this branch. Use the slugified version of the app name. **Note**: The list of users, apps, and teams in total is limited to 100 items.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_set_app_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_set_status_check_contexts.go b/MCP/tools/repos/repos_set_status_check_contexts.go new file mode 100644 index 0000000..c1ffedb --- /dev/null +++ b/MCP/tools/repos/repos_set_status_check_contexts.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_set_status_check_contextsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks/contexts", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []string + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_set_status_check_contextsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_branches_branch_protection_required_status_checks_contexts", + mcp.WithDescription("Set status check contexts"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_set_status_check_contextsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_set_team_access_restrictions.go b/MCP/tools/repos/repos_set_team_access_restrictions.go new file mode 100644 index 0000000..cd8f57d --- /dev/null +++ b/MCP/tools/repos/repos_set_team_access_restrictions.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_set_team_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/teams", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_set_team_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_branches_branch_protection_restrictions_teams", + mcp.WithDescription("Set team access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_set_team_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_set_user_access_restrictions.go b/MCP/tools/repos/repos_set_user_access_restrictions.go new file mode 100644 index 0000000..8d11516 --- /dev/null +++ b/MCP/tools/repos/repos_set_user_access_restrictions.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_set_user_access_restrictionsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/restrictions/users", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_set_user_access_restrictionsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_branches_branch_protection_restrictions_users", + mcp.WithDescription("Set user access restrictions"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("users", mcp.Required(), mcp.Description("Input parameter: The username for users")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_set_user_access_restrictionsHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_test_push_webhook.go b/MCP/tools/repos/repos_test_push_webhook.go new file mode 100644 index 0000000..9fb8190 --- /dev/null +++ b/MCP/tools/repos/repos_test_push_webhook.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_test_push_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/tests", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_test_push_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_hooks_hook_id_tests", + mcp.WithDescription("Test the push repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_test_push_webhookHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_transfer.go b/MCP/tools/repos/repos_transfer.go new file mode 100644 index 0000000..8627fb1 --- /dev/null +++ b/MCP/tools/repos/repos_transfer.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_transferHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/transfer", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_transferTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_transfer", + mcp.WithDescription("Transfer a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithArray("team_ids", mcp.Description("Input parameter: ID of the team or teams to add to the repository. Teams can only be added to organization-owned repositories.")), + mcp.WithString("new_name", mcp.Description("Input parameter: The new name to be given to the repository.")), + mcp.WithString("new_owner", mcp.Required(), mcp.Description("Input parameter: The username or organization name the repository will be transferred to.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_transferHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update.go b/MCP/tools/repos/repos_update.go new file mode 100644 index 0000000..be1c9bf --- /dev/null +++ b/MCP/tools/repos/repos_update.go @@ -0,0 +1,129 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_updateHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_updateTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo", + mcp.WithDescription("Update a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithBoolean("use_squash_pr_title_as_default", mcp.Description("Input parameter: Either `true` to allow squash-merge commits to use pull request title, or `false` to use commit message. **This property is closing down. Please use `squash_merge_commit_title` instead.")), + mcp.WithBoolean("archived", mcp.Description("Input parameter: Whether to archive this repository. `false` will unarchive a previously archived repository.")), + mcp.WithString("homepage", mcp.Description("Input parameter: A URL with more information about the repository.")), + mcp.WithString("default_branch", mcp.Description("Input parameter: Updates the default branch for this repository.")), + mcp.WithBoolean("web_commit_signoff_required", mcp.Description("Input parameter: Either `true` to require contributors to sign off on web-based commits, or `false` to not require contributors to sign off on web-based commits.")), + mcp.WithBoolean("has_wiki", mcp.Description("Input parameter: Either `true` to enable the wiki for this repository or `false` to disable it.")), + mcp.WithBoolean("allow_auto_merge", mcp.Description("Input parameter: Either `true` to allow auto-merge on pull requests, or `false` to disallow auto-merge.")), + mcp.WithBoolean("allow_squash_merge", mcp.Description("Input parameter: Either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.")), + mcp.WithString("squash_merge_commit_title", mcp.Description("Input parameter: Required when using `squash_merge_commit_message`.\n\nThe default value for a squash merge commit title:\n\n- `PR_TITLE` - default to the pull request's title.\n- `COMMIT_OR_PR_TITLE` - default to the commit's title (if only one commit) or the pull request's title (when more than one commit).")), + mcp.WithString("visibility", mcp.Description("Input parameter: The visibility of the repository.")), + mcp.WithString("merge_commit_message", mcp.Description("Input parameter: The default value for a merge commit message.\n\n- `PR_TITLE` - default to the pull request's title.\n- `PR_BODY` - default to the pull request's body.\n- `BLANK` - default to a blank commit message.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the repository.")), + mcp.WithString("squash_merge_commit_message", mcp.Description("Input parameter: The default value for a squash merge commit message:\n\n- `PR_BODY` - default to the pull request's body.\n- `COMMIT_MESSAGES` - default to the branch's commit messages.\n- `BLANK` - default to a blank commit message.")), + mcp.WithBoolean("allow_merge_commit", mcp.Description("Input parameter: Either `true` to allow merging pull requests with a merge commit, or `false` to prevent merging pull requests with merge commits.")), + mcp.WithBoolean("allow_update_branch", mcp.Description("Input parameter: Either `true` to always allow a pull request head branch that is behind its base branch to be updated even if it is not required to be up to date before merging, or false otherwise.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the repository.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Either `true` to make the repository private or `false` to make it public. Default: `false`. \n**Note**: You will get a `422` error if the organization restricts [changing repository visibility](https://docs.github.com/articles/repository-permission-levels-for-an-organization#changing-the-visibility-of-repositories) to organization owners and a non-owner tries to change the value of private.")), + mcp.WithBoolean("delete_branch_on_merge", mcp.Description("Input parameter: Either `true` to allow automatically deleting head branches when pull requests are merged, or `false` to prevent automatic deletion.")), + mcp.WithBoolean("has_issues", mcp.Description("Input parameter: Either `true` to enable issues for this repository or `false` to disable them.")), + mcp.WithBoolean("is_template", mcp.Description("Input parameter: Either `true` to make this repo available as a template repository or `false` to prevent it.")), + mcp.WithString("merge_commit_title", mcp.Description("Input parameter: Required when using `merge_commit_message`.\n\nThe default value for a merge commit title.\n\n- `PR_TITLE` - default to the pull request's title.\n- `MERGE_MESSAGE` - default to the classic title for a merge message (e.g., Merge pull request #123 from branch-name).")), + mcp.WithObject("security_and_analysis", mcp.Description("Input parameter: Specify which security and analysis features to enable or disable for the repository.\n\nTo use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see \"[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization).\"\n\nFor example, to enable GitHub Advanced Security, use this data in the body of the `PATCH` request:\n`{ \"security_and_analysis\": {\"advanced_security\": { \"status\": \"enabled\" } } }`.\n\nYou can check which security and analysis features are currently enabled by using a `GET /repos/{owner}/{repo}` request.")), + mcp.WithBoolean("allow_rebase_merge", mcp.Description("Input parameter: Either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging.")), + mcp.WithBoolean("allow_forking", mcp.Description("Input parameter: Either `true` to allow private forks, or `false` to prevent private forks.")), + mcp.WithBoolean("has_projects", mcp.Description("Input parameter: Either `true` to enable projects for this repository or `false` to disable them. **Note:** If you're creating a repository in an organization that has disabled repository projects, the default is `false`, and if you pass `true`, the API returns an error.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_updateHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_branch_protection.go b/MCP/tools/repos/repos_update_branch_protection.go new file mode 100644 index 0000000..94f70b3 --- /dev/null +++ b/MCP/tools/repos/repos_update_branch_protection.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_branch_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_branch_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_branches_branch_protection", + mcp.WithDescription("Update branch protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithObject("restrictions", mcp.Required(), mcp.Description("Input parameter: Restrict who can push to the protected branch. User, app, and team `restrictions` are only available for organization-owned repositories. Set to `null` to disable.")), + mcp.WithBoolean("allow_deletions", mcp.Description("Input parameter: Allows deletion of the protected branch by anyone with write access to the repository. Set to `false` to prevent deletion of the protected branch. Default: `false`. For more information, see \"[Enabling force pushes to a protected branch](https://docs.github.com/github/administering-a-repository/enabling-force-pushes-to-a-protected-branch)\" in the GitHub Help documentation.")), + mcp.WithBoolean("block_creations", mcp.Description("Input parameter: If set to `true`, the `restrictions` branch protection settings which limits who can push will also block pushes which create new branches, unless the push is initiated by a user, team, or app which has the ability to push. Set to `true` to restrict new branch creation. Default: `false`.")), + mcp.WithBoolean("required_conversation_resolution", mcp.Description("Input parameter: Requires all conversations on code to be resolved before a pull request can be merged into a branch that matches this rule. Set to `false` to disable. Default: `false`.")), + mcp.WithBoolean("allow_force_pushes", mcp.Description("Input parameter: Permits force pushes to the protected branch by anyone with write access to the repository. Set to `true` to allow force pushes. Set to `false` or `null` to block force pushes. Default: `false`. For more information, see \"[Enabling force pushes to a protected branch](https://docs.github.com/github/administering-a-repository/enabling-force-pushes-to-a-protected-branch)\" in the GitHub Help documentation.\"")), + mcp.WithBoolean("allow_fork_syncing", mcp.Description("Input parameter: Whether users can pull changes from upstream when the branch is locked. Set to `true` to allow fork syncing. Set to `false` to prevent fork syncing. Default: `false`.")), + mcp.WithBoolean("enforce_admins", mcp.Required(), mcp.Description("Input parameter: Enforce all configured restrictions for administrators. Set to `true` to enforce required status checks for repository administrators. Set to `null` to disable.")), + mcp.WithBoolean("lock_branch", mcp.Description("Input parameter: Whether to set the branch as read-only. If this is true, users will not be able to push to the branch. Default: `false`.")), + mcp.WithObject("required_pull_request_reviews", mcp.Required(), mcp.Description("Input parameter: Require at least one approving review on a pull request, before merging. Set to `null` to disable.")), + mcp.WithBoolean("required_linear_history", mcp.Description("Input parameter: Enforces a linear commit Git history, which prevents anyone from pushing merge commits to a branch. Set to `true` to enforce a linear commit history. Set to `false` to disable a linear commit Git history. Your repository must allow squash merging or rebase merging before you can enable a linear commit history. Default: `false`. For more information, see \"[Requiring a linear commit history](https://docs.github.com/github/administering-a-repository/requiring-a-linear-commit-history)\" in the GitHub Help documentation.")), + mcp.WithObject("required_status_checks", mcp.Required(), mcp.Description("Input parameter: Require status checks to pass before merging. Set to `null` to disable.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_branch_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_commit_comment.go b/MCP/tools/repos/repos_update_commit_comment.go new file mode 100644 index 0000000..a93ef7b --- /dev/null +++ b/MCP/tools/repos/repos_update_commit_comment.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_commit_commentHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + comment_idVal, ok := args["comment_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_id"), nil + } + comment_id, ok := comment_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/comments/%s", cfg.BaseURL, owner, repo, comment_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_commit_commentTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_comments_comment_id", + mcp.WithDescription("Update a commit comment"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("comment_id", mcp.Required(), mcp.Description("The unique identifier of the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The contents of the comment")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_commit_commentHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_deployment_branch_policy.go b/MCP/tools/repos/repos_update_deployment_branch_policy.go new file mode 100644 index 0000000..07bcca5 --- /dev/null +++ b/MCP/tools/repos/repos_update_deployment_branch_policy.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_deployment_branch_policyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + environment_nameVal, ok := args["environment_name"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: environment_name"), nil + } + environment_name, ok := environment_nameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: environment_name"), nil + } + branch_policy_idVal, ok := args["branch_policy_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch_policy_id"), nil + } + branch_policy_id, ok := branch_policy_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch_policy_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/environments/%s/deployment-branch-policies/%s", cfg.BaseURL, owner, repo, environment_name, branch_policy_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_deployment_branch_policyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_environments_environment_name_deployment-branch-policies_branch_policy_id", + mcp.WithDescription("Update a deployment branch policy"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("environment_name", mcp.Required(), mcp.Description("The name of the environment. The name must be URL encoded. For example, any slashes in the name must be replaced with `%2F`.")), + mcp.WithNumber("branch_policy_id", mcp.Required(), mcp.Description("The unique identifier of the branch policy.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name pattern that branches must match in order to deploy to the environment.\n\nWildcard characters will not match `/`. For example, to match branches that begin with `release/` and contain an additional single slash, use `release/*/*`.\nFor more information about pattern matching syntax, see the [Ruby File.fnmatch documentation](https://ruby-doc.org/core-2.5.1/File.html#method-c-fnmatch).")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_deployment_branch_policyHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_information_about_pages_site.go b/MCP/tools/repos/repos_update_information_about_pages_site.go new file mode 100644 index 0000000..59480a9 --- /dev/null +++ b/MCP/tools/repos/repos_update_information_about_pages_site.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_information_about_pages_siteHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/pages", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_information_about_pages_siteTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_pages", + mcp.WithDescription("Update information about a GitHub Pages site"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("build_type", mcp.Description("Input parameter: The process by which the GitHub Pages site will be built. `workflow` means that the site is built by a custom GitHub Actions workflow. `legacy` means that the site is built by GitHub when changes are pushed to a specific branch.")), + mcp.WithString("cname", mcp.Description("Input parameter: Specify a custom domain for the repository. Sending a `null` value will remove the custom domain. For more about custom domains, see \"[Using a custom domain with GitHub Pages](https://docs.github.com/pages/configuring-a-custom-domain-for-your-github-pages-site).\"")), + mcp.WithBoolean("https_enforced", mcp.Description("Input parameter: Specify whether HTTPS should be enforced for the repository.")), + mcp.WithString("source", mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_information_about_pages_siteHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_invitation.go b/MCP/tools/repos/repos_update_invitation.go new file mode 100644 index 0000000..222a6f7 --- /dev/null +++ b/MCP/tools/repos/repos_update_invitation.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_invitationHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + invitation_idVal, ok := args["invitation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: invitation_id"), nil + } + invitation_id, ok := invitation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: invitation_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/invitations/%s", cfg.BaseURL, owner, repo, invitation_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_invitationTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_invitations_invitation_id", + mcp.WithDescription("Update a repository invitation"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("invitation_id", mcp.Required(), mcp.Description("The unique identifier of the invitation.")), + mcp.WithString("permissions", mcp.Description("Input parameter: The permissions that the associated user will have on the repository. Valid values are `read`, `write`, `maintain`, `triage`, and `admin`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_invitationHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_org_ruleset.go b/MCP/tools/repos/repos_update_org_ruleset.go new file mode 100644 index 0000000..b907b8f --- /dev/null +++ b/MCP/tools/repos/repos_update_org_ruleset.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_org_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/rulesets/%s", cfg.BaseURL, org, ruleset_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_org_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_rulesets_ruleset_id", + mcp.WithDescription("Update an organization repository ruleset"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + mcp.WithArray("bypass_actors", mcp.Description("Input parameter: The actors that can bypass the rules in this ruleset")), + mcp.WithString("conditions", mcp.Description("Input parameter: Conditions for an organization ruleset.\nThe branch and tag rulesets conditions object should contain both `repository_name` and `ref_name` properties, or both `repository_id` and `ref_name` properties, or both `repository_property` and `ref_name` properties.\nThe push rulesets conditions object does not require the `ref_name` property.\nFor repository policy rulesets, the conditions object should only contain the `repository_name`, the `repository_id`, or the `repository_property`.")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement level of the ruleset. `evaluate` allows admins to test rules before enforcing them. Admins can view insights on the Rule Insights page (`evaluate` is only available with GitHub Enterprise).")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the ruleset.")), + mcp.WithArray("rules", mcp.Description("Input parameter: An array of rules within the ruleset.")), + mcp.WithString("target", mcp.Description("Input parameter: The target of the ruleset")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_org_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_pull_request_review_protection.go b/MCP/tools/repos/repos_update_pull_request_review_protection.go new file mode 100644 index 0000000..aff2d6e --- /dev/null +++ b/MCP/tools/repos/repos_update_pull_request_review_protection.go @@ -0,0 +1,119 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_pull_request_review_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_pull_request_reviews", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_pull_request_review_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_branches_branch_protection_required_pull_request_reviews", + mcp.WithDescription("Update pull request review protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithBoolean("require_code_owner_reviews", mcp.Description("Input parameter: Blocks merging pull requests until [code owners](https://docs.github.com/articles/about-code-owners/) have reviewed.")), + mcp.WithBoolean("require_last_push_approval", mcp.Description("Input parameter: Whether the most recent push must be approved by someone other than the person who pushed it. Default: `false`")), + mcp.WithNumber("required_approving_review_count", mcp.Description("Input parameter: Specifies the number of reviewers required to approve pull requests. Use a number between 1 and 6 or 0 to not require reviewers.")), + mcp.WithObject("bypass_pull_request_allowances", mcp.Description("Input parameter: Allow specific users, teams, or apps to bypass pull request requirements.")), + mcp.WithBoolean("dismiss_stale_reviews", mcp.Description("Input parameter: Set to `true` if you want to automatically dismiss approving reviews when someone pushes a new commit.")), + mcp.WithObject("dismissal_restrictions", mcp.Description("Input parameter: Specify which users, teams, and apps can dismiss pull request reviews. Pass an empty `dismissal_restrictions` object to disable. User and team `dismissal_restrictions` are only available for organization-owned repositories. Omit this parameter for personal repositories.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_pull_request_review_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_release.go b/MCP/tools/repos/repos_update_release.go new file mode 100644 index 0000000..9050931 --- /dev/null +++ b/MCP/tools/repos/repos_update_release.go @@ -0,0 +1,121 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_releaseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + release_idVal, ok := args["release_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: release_id"), nil + } + release_id, ok := release_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: release_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/%s", cfg.BaseURL, owner, repo, release_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Release + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_releaseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_releases_release_id", + mcp.WithDescription("Update a release"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("release_id", mcp.Required(), mcp.Description("The unique identifier of the release.")), + mcp.WithString("tag_name", mcp.Description("Input parameter: The name of the tag.")), + mcp.WithString("target_commitish", mcp.Description("Input parameter: Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Unused if the Git tag already exists. Default: the repository's default branch.")), + mcp.WithString("body", mcp.Description("Input parameter: Text describing the contents of the tag.")), + mcp.WithString("discussion_category_name", mcp.Description("Input parameter: If specified, a discussion of the specified category is created and linked to the release. The value must be a category that already exists in the repository. If there is already a discussion linked to the release, this parameter is ignored. For more information, see \"[Managing categories for discussions in your repository](https://docs.github.com/discussions/managing-discussions-for-your-community/managing-categories-for-discussions-in-your-repository).\"")), + mcp.WithBoolean("draft", mcp.Description("Input parameter: `true` makes the release a draft, and `false` publishes the release.")), + mcp.WithString("make_latest", mcp.Description("Input parameter: Specifies whether this release should be set as the latest release for the repository. Drafts and prereleases cannot be set as latest. Defaults to `true` for newly published releases. `legacy` specifies that the latest release should be determined based on the release creation date and higher semantic version.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the release.")), + mcp.WithBoolean("prerelease", mcp.Description("Input parameter: `true` to identify the release as a prerelease, `false` to identify the release as a full release.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_releaseHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_release_asset.go b/MCP/tools/repos/repos_update_release_asset.go new file mode 100644 index 0000000..704d5ce --- /dev/null +++ b/MCP/tools/repos/repos_update_release_asset.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_release_assetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + asset_idVal, ok := args["asset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: asset_id"), nil + } + asset_id, ok := asset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: asset_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/releases/assets/%s", cfg.BaseURL, owner, repo, asset_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_release_assetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_releases_assets_asset_id", + mcp.WithDescription("Update a release asset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("asset_id", mcp.Required(), mcp.Description("The unique identifier of the asset.")), + mcp.WithString("state", mcp.Description("")), + mcp.WithString("label", mcp.Description("Input parameter: An alternate short description of the asset. Used in place of the filename.")), + mcp.WithString("name", mcp.Description("Input parameter: The file name of the asset.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_release_assetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_repo_ruleset.go b/MCP/tools/repos/repos_update_repo_ruleset.go new file mode 100644 index 0000000..1614bac --- /dev/null +++ b/MCP/tools/repos/repos_update_repo_ruleset.go @@ -0,0 +1,119 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_repo_rulesetHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ruleset_idVal, ok := args["ruleset_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ruleset_id"), nil + } + ruleset_id, ok := ruleset_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ruleset_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/rulesets/%s", cfg.BaseURL, owner, repo, ruleset_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_repo_rulesetTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_repos_owner_repo_rulesets_ruleset_id", + mcp.WithDescription("Update a repository ruleset"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("ruleset_id", mcp.Required(), mcp.Description("The ID of the ruleset.")), + mcp.WithObject("conditions", mcp.Description("Input parameter: Parameters for a repository ruleset ref name condition")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement level of the ruleset. `evaluate` allows admins to test rules before enforcing them. Admins can view insights on the Rule Insights page (`evaluate` is only available with GitHub Enterprise).")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the ruleset.")), + mcp.WithArray("rules", mcp.Description("Input parameter: An array of rules within the ruleset.")), + mcp.WithString("target", mcp.Description("Input parameter: The target of the ruleset")), + mcp.WithArray("bypass_actors", mcp.Description("Input parameter: The actors that can bypass the rules in this ruleset")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_repo_rulesetHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_status_check_protection.go b/MCP/tools/repos/repos_update_status_check_protection.go new file mode 100644 index 0000000..6f3fc52 --- /dev/null +++ b/MCP/tools/repos/repos_update_status_check_protection.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_status_check_protectionHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + branchVal, ok := args["branch"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: branch"), nil + } + branch, ok := branchVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: branch"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/branches/%s/protection/required_status_checks", cfg.BaseURL, owner, repo, branch) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_status_check_protectionTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_branches_branch_protection_required_status_checks", + mcp.WithDescription("Update status check protection"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("branch", mcp.Required(), mcp.Description("The name of the branch. Cannot contain wildcard characters. To use wildcard characters in branch names, use [the GraphQL API](https://docs.github.com/graphql).")), + mcp.WithArray("contexts", mcp.Description("Input parameter: **Closing down notice**: The list of status checks to require in order to merge into this branch. If any of these checks have recently been set by a particular GitHub App, they will be required to come from that app in future for the branch to merge. Use `checks` instead of `contexts` for more fine-grained control.")), + mcp.WithBoolean("strict", mcp.Description("Input parameter: Require branches to be up to date before merging.")), + mcp.WithArray("checks", mcp.Description("Input parameter: The list of status checks to require in order to merge into this branch.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_status_check_protectionHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_webhook.go b/MCP/tools/repos/repos_update_webhook.go new file mode 100644 index 0000000..1ae97c7 --- /dev/null +++ b/MCP/tools/repos/repos_update_webhook.go @@ -0,0 +1,118 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_webhookHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Hook + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_webhookTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_hooks_hook_id", + mcp.WithDescription("Update a repository webhook"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithArray("add_events", mcp.Description("Input parameter: Determines a list of events to be added to the list of events that the Hook triggers for.")), + mcp.WithObject("config", mcp.Description("Input parameter: Configuration object of the webhook")), + mcp.WithArray("events", mcp.Description("Input parameter: Determines what [events](https://docs.github.com/webhooks/event-payloads) the hook is triggered for. This replaces the entire array of events.")), + mcp.WithArray("remove_events", mcp.Description("Input parameter: Determines a list of events to be removed from the list of events that the Hook triggers for.")), + mcp.WithBoolean("active", mcp.Description("Input parameter: Determines if notifications are sent when the webhook is triggered. Set to `true` to send notifications.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_webhookHandler(cfg), + } +} diff --git a/MCP/tools/repos/repos_update_webhook_config_for_repo.go b/MCP/tools/repos/repos_update_webhook_config_for_repo.go new file mode 100644 index 0000000..cafbfb5 --- /dev/null +++ b/MCP/tools/repos/repos_update_webhook_config_for_repo.go @@ -0,0 +1,117 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Repos_update_webhook_config_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + hook_idVal, ok := args["hook_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: hook_id"), nil + } + hook_id, ok := hook_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: hook_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/hooks/%s/config", cfg.BaseURL, owner, repo, hook_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateRepos_update_webhook_config_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_hooks_hook_id_config", + mcp.WithDescription("Update a webhook configuration for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("hook_id", mcp.Required(), mcp.Description("The unique identifier of the hook. You can find this value in the `X-GitHub-Hook-ID` header of a webhook delivery.")), + mcp.WithString("secret", mcp.Description("Input parameter: If provided, the `secret` will be used as the `key` to generate the HMAC hex digest value for [delivery signature headers](https://docs.github.com/webhooks/event-payloads/#delivery-headers).")), + mcp.WithString("url", mcp.Description("Input parameter: The URL to which the payloads will be delivered.")), + mcp.WithString("content_type", mcp.Description("Input parameter: The media type used to serialize the payloads. Supported values include `json` and `form`. The default is `form`.")), + mcp.WithString("insecure_ssl", mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Repos_update_webhook_config_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/search/search_code.go b/MCP/tools/search/search_code.go new file mode 100644 index 0000000..e8c2923 --- /dev/null +++ b/MCP/tools/search/search_code.go @@ -0,0 +1,94 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_codeHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["order"]; ok { + queryParams = append(queryParams, fmt.Sprintf("order=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/code%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_codeTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_code", + mcp.WithDescription("Search code"), + mcp.WithString("q", mcp.Required(), mcp.Description("The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query). See \"[Searching code](https://docs.github.com/search-github/searching-on-github/searching-code)\" for a detailed list of qualifiers.")), + mcp.WithString("sort", mcp.Description("**This field is closing down.** Sorts the results of your query. Can only be `indexed`, which indicates how recently a file has been indexed by the GitHub search infrastructure. Default: [best match](https://docs.github.com/rest/search/search#ranking-search-results)")), + mcp.WithString("order", mcp.Description("**This field is closing down.** Determines whether the first search result returned is the highest number of matches (`desc`) or lowest number of matches (`asc`). This parameter is ignored unless you provide `sort`. ")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_codeHandler(cfg), + } +} diff --git a/MCP/tools/search/search_commits.go b/MCP/tools/search/search_commits.go new file mode 100644 index 0000000..012ac9f --- /dev/null +++ b/MCP/tools/search/search_commits.go @@ -0,0 +1,94 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_commitsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["order"]; ok { + queryParams = append(queryParams, fmt.Sprintf("order=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/commits%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_commitsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_commits", + mcp.WithDescription("Search commits"), + mcp.WithString("q", mcp.Required(), mcp.Description("The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query). See \"[Searching commits](https://docs.github.com/search-github/searching-on-github/searching-commits)\" for a detailed list of qualifiers.")), + mcp.WithString("sort", mcp.Description("Sorts the results of your query by `author-date` or `committer-date`. Default: [best match](https://docs.github.com/rest/search/search#ranking-search-results)")), + mcp.WithString("order", mcp.Description("Determines whether the first search result returned is the highest number of matches (`desc`) or lowest number of matches (`asc`). This parameter is ignored unless you provide `sort`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_commitsHandler(cfg), + } +} diff --git a/MCP/tools/search/search_issues_and_pull_requests.go b/MCP/tools/search/search_issues_and_pull_requests.go new file mode 100644 index 0000000..313b1c3 --- /dev/null +++ b/MCP/tools/search/search_issues_and_pull_requests.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_issues_and_pull_requestsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["order"]; ok { + queryParams = append(queryParams, fmt.Sprintf("order=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["advanced_search"]; ok { + queryParams = append(queryParams, fmt.Sprintf("advanced_search=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/issues%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_issues_and_pull_requestsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_issues", + mcp.WithDescription("Search issues and pull requests"), + mcp.WithString("q", mcp.Required(), mcp.Description("The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query). See \"[Searching issues and pull requests](https://docs.github.com/search-github/searching-on-github/searching-issues-and-pull-requests)\" for a detailed list of qualifiers.")), + mcp.WithString("sort", mcp.Description("Sorts the results of your query by the number of `comments`, `reactions`, `reactions-+1`, `reactions--1`, `reactions-smile`, `reactions-thinking_face`, `reactions-heart`, `reactions-tada`, or `interactions`. You can also sort results by how recently the items were `created` or `updated`, Default: [best match](https://docs.github.com/rest/search/search#ranking-search-results)")), + mcp.WithString("order", mcp.Description("Determines whether the first search result returned is the highest number of matches (`desc`) or lowest number of matches (`asc`). This parameter is ignored unless you provide `sort`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("advanced_search", mcp.Description("Set to `true` to use advanced search.\nExample: `http://api.github.com/search/issues?q={query}&advanced_search=true`")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_issues_and_pull_requestsHandler(cfg), + } +} diff --git a/MCP/tools/search/search_labels.go b/MCP/tools/search/search_labels.go new file mode 100644 index 0000000..9d215f7 --- /dev/null +++ b/MCP/tools/search/search_labels.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_labelsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["repository_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("repository_id=%v", val)) + } + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["order"]; ok { + queryParams = append(queryParams, fmt.Sprintf("order=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/labels%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_labelsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_labels", + mcp.WithDescription("Search labels"), + mcp.WithNumber("repository_id", mcp.Required(), mcp.Description("The id of the repository.")), + mcp.WithString("q", mcp.Required(), mcp.Description("The search keywords. This endpoint does not accept qualifiers in the query. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query).")), + mcp.WithString("sort", mcp.Description("Sorts the results of your query by when the label was `created` or `updated`. Default: [best match](https://docs.github.com/rest/search/search#ranking-search-results)")), + mcp.WithString("order", mcp.Description("Determines whether the first search result returned is the highest number of matches (`desc`) or lowest number of matches (`asc`). This parameter is ignored unless you provide `sort`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_labelsHandler(cfg), + } +} diff --git a/MCP/tools/search/search_repos.go b/MCP/tools/search/search_repos.go new file mode 100644 index 0000000..899a19a --- /dev/null +++ b/MCP/tools/search/search_repos.go @@ -0,0 +1,94 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_reposHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["order"]; ok { + queryParams = append(queryParams, fmt.Sprintf("order=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/repositories%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_reposTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_repositories", + mcp.WithDescription("Search repositories"), + mcp.WithString("q", mcp.Required(), mcp.Description("The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query). See \"[Searching for repositories](https://docs.github.com/articles/searching-for-repositories/)\" for a detailed list of qualifiers.")), + mcp.WithString("sort", mcp.Description("Sorts the results of your query by number of `stars`, `forks`, or `help-wanted-issues` or how recently the items were `updated`. Default: [best match](https://docs.github.com/rest/search/search#ranking-search-results)")), + mcp.WithString("order", mcp.Description("Determines whether the first search result returned is the highest number of matches (`desc`) or lowest number of matches (`asc`). This parameter is ignored unless you provide `sort`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_reposHandler(cfg), + } +} diff --git a/MCP/tools/search/search_topics.go b/MCP/tools/search/search_topics.go new file mode 100644 index 0000000..7c7ab1d --- /dev/null +++ b/MCP/tools/search/search_topics.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_topicsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/topics%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_topicsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_topics", + mcp.WithDescription("Search topics"), + mcp.WithString("q", mcp.Required(), mcp.Description("The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query).")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_topicsHandler(cfg), + } +} diff --git a/MCP/tools/search/search_users.go b/MCP/tools/search/search_users.go new file mode 100644 index 0000000..68d1aee --- /dev/null +++ b/MCP/tools/search/search_users.go @@ -0,0 +1,94 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Search_usersHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["q"]; ok { + queryParams = append(queryParams, fmt.Sprintf("q=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["order"]; ok { + queryParams = append(queryParams, fmt.Sprintf("order=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/search/users%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSearch_usersTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_search_users", + mcp.WithDescription("Search users"), + mcp.WithString("q", mcp.Required(), mcp.Description("The query contains one or more search keywords and qualifiers. Qualifiers allow you to limit your search to specific areas of GitHub. The REST API supports the same qualifiers as the web interface for GitHub. To learn more about the format of the query, see [Constructing a search query](https://docs.github.com/rest/search/search#constructing-a-search-query). See \"[Searching users](https://docs.github.com/search-github/searching-on-github/searching-users)\" for a detailed list of qualifiers.")), + mcp.WithString("sort", mcp.Description("Sorts the results of your query by number of `followers` or `repositories`, or when the person `joined` GitHub. Default: [best match](https://docs.github.com/rest/search/search#ranking-search-results)")), + mcp.WithString("order", mcp.Description("Determines whether the first search result returned is the highest number of matches (`desc`) or lowest number of matches (`asc`). This parameter is ignored unless you provide `sort`.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Search_usersHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_create_push_protection_bypass.go b/MCP/tools/secret_scanning/secret_scanning_create_push_protection_bypass.go new file mode 100644 index 0000000..6489cb4 --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_create_push_protection_bypass.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_create_push_protection_bypassHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/secret-scanning/push-protection-bypasses", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_create_push_protection_bypassTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_secret-scanning_push-protection-bypasses", + mcp.WithDescription("Create a push protection bypass"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("placeholder_id", mcp.Required(), mcp.Description("Input parameter: The ID of the push protection bypass placeholder. This value is returned on any push protected routes.")), + mcp.WithString("reason", mcp.Required(), mcp.Description("Input parameter: The reason for bypassing push protection.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_create_push_protection_bypassHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_get_alert.go b/MCP/tools/secret_scanning/secret_scanning_get_alert.go new file mode 100644 index 0000000..c1671f9 --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_get_alert.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_get_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["hide_secret"]; ok { + queryParams = append(queryParams, fmt.Sprintf("hide_secret=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/secret-scanning/alerts/%s%s", cfg.BaseURL, owner, repo, alert_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_get_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_secret-scanning_alerts_alert_number", + mcp.WithDescription("Get a secret scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + mcp.WithBoolean("hide_secret", mcp.Description("A boolean value representing whether or not to hide literal secrets in the results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_get_alertHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_get_scan_history.go b/MCP/tools/secret_scanning/secret_scanning_get_scan_history.go new file mode 100644 index 0000000..ff61bb4 --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_get_scan_history.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_get_scan_historyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/secret-scanning/scan-history", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_get_scan_historyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_secret-scanning_scan-history", + mcp.WithDescription("Get secret scanning scan history for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_get_scan_historyHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_enterprise.go b/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_enterprise.go new file mode 100644 index 0000000..e496a9c --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_enterprise.go @@ -0,0 +1,131 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_list_alerts_for_enterpriseHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + enterpriseVal, ok := args["enterprise"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: enterprise"), nil + } + enterprise, ok := enterpriseVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: enterprise"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["secret_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("secret_type=%v", val)) + } + if val, ok := args["resolution"]; ok { + queryParams = append(queryParams, fmt.Sprintf("resolution=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["validity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("validity=%v", val)) + } + if val, ok := args["is_publicly_leaked"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_publicly_leaked=%v", val)) + } + if val, ok := args["is_multi_repo"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_multi_repo=%v", val)) + } + if val, ok := args["hide_secret"]; ok { + queryParams = append(queryParams, fmt.Sprintf("hide_secret=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/enterprises/%s/secret-scanning/alerts%s", cfg.BaseURL, enterprise, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_list_alerts_for_enterpriseTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_enterprises_enterprise_secret-scanning_alerts", + mcp.WithDescription("List secret scanning alerts for an enterprise"), + mcp.WithString("enterprise", mcp.Required(), mcp.Description("The slug version of the enterprise name. You can also substitute this value with the enterprise id.")), + mcp.WithString("state", mcp.Description("Set to `open` or `resolved` to only list secret scanning alerts in a specific state.")), + mcp.WithString("secret_type", mcp.Description("A comma-separated list of secret types to return. All default secret patterns are returned. To return generic patterns, pass the token name(s) in the parameter. See \"[Supported secret scanning patterns](https://docs.github.com/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets)\" for a complete list of secret types.")), + mcp.WithString("resolution", mcp.Description("A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed. Valid resolutions are `false_positive`, `wont_fix`, `revoked`, `pattern_edited`, `pattern_deleted` or `used_in_tests`.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by. `created` means when the alert was created. `updated` means when the alert was updated or resolved.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("validity", mcp.Description("A comma-separated list of validities that, when present, will return alerts that match the validities in this list. Valid options are `active`, `inactive`, and `unknown`.")), + mcp.WithBoolean("is_publicly_leaked", mcp.Description("A boolean value representing whether or not to filter alerts by the publicly-leaked tag being present.")), + mcp.WithBoolean("is_multi_repo", mcp.Description("A boolean value representing whether or not to filter alerts by the multi-repo tag being present.")), + mcp.WithBoolean("hide_secret", mcp.Description("A boolean value representing whether or not to hide literal secrets in the results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_list_alerts_for_enterpriseHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_org.go b/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_org.go new file mode 100644 index 0000000..b513c69 --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_org.go @@ -0,0 +1,135 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_list_alerts_for_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["secret_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("secret_type=%v", val)) + } + if val, ok := args["resolution"]; ok { + queryParams = append(queryParams, fmt.Sprintf("resolution=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["validity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("validity=%v", val)) + } + if val, ok := args["is_publicly_leaked"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_publicly_leaked=%v", val)) + } + if val, ok := args["is_multi_repo"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_multi_repo=%v", val)) + } + if val, ok := args["hide_secret"]; ok { + queryParams = append(queryParams, fmt.Sprintf("hide_secret=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/secret-scanning/alerts%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_list_alerts_for_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_secret-scanning_alerts", + mcp.WithDescription("List secret scanning alerts for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("Set to `open` or `resolved` to only list secret scanning alerts in a specific state.")), + mcp.WithString("secret_type", mcp.Description("A comma-separated list of secret types to return. All default secret patterns are returned. To return generic patterns, pass the token name(s) in the parameter. See \"[Supported secret scanning patterns](https://docs.github.com/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets)\" for a complete list of secret types.")), + mcp.WithString("resolution", mcp.Description("A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed. Valid resolutions are `false_positive`, `wont_fix`, `revoked`, `pattern_edited`, `pattern_deleted` or `used_in_tests`.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by. `created` means when the alert was created. `updated` means when the alert was updated or resolved.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for events before this cursor. To receive an initial cursor on your first request, include an empty \"before\" query string.")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for events after this cursor. To receive an initial cursor on your first request, include an empty \"after\" query string.")), + mcp.WithString("validity", mcp.Description("A comma-separated list of validities that, when present, will return alerts that match the validities in this list. Valid options are `active`, `inactive`, and `unknown`.")), + mcp.WithBoolean("is_publicly_leaked", mcp.Description("A boolean value representing whether or not to filter alerts by the publicly-leaked tag being present.")), + mcp.WithBoolean("is_multi_repo", mcp.Description("A boolean value representing whether or not to filter alerts by the multi-repo tag being present.")), + mcp.WithBoolean("hide_secret", mcp.Description("A boolean value representing whether or not to hide literal secrets in the results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_list_alerts_for_orgHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_repo.go b/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_repo.go new file mode 100644 index 0000000..27d610d --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_list_alerts_for_repo.go @@ -0,0 +1,144 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_list_alerts_for_repoHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + if val, ok := args["secret_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("secret_type=%v", val)) + } + if val, ok := args["resolution"]; ok { + queryParams = append(queryParams, fmt.Sprintf("resolution=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["validity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("validity=%v", val)) + } + if val, ok := args["is_publicly_leaked"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_publicly_leaked=%v", val)) + } + if val, ok := args["is_multi_repo"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_multi_repo=%v", val)) + } + if val, ok := args["hide_secret"]; ok { + queryParams = append(queryParams, fmt.Sprintf("hide_secret=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/secret-scanning/alerts%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_list_alerts_for_repoTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_secret-scanning_alerts", + mcp.WithDescription("List secret scanning alerts for a repository"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("state", mcp.Description("Set to `open` or `resolved` to only list secret scanning alerts in a specific state.")), + mcp.WithString("secret_type", mcp.Description("A comma-separated list of secret types to return. All default secret patterns are returned. To return generic patterns, pass the token name(s) in the parameter. See \"[Supported secret scanning patterns](https://docs.github.com/code-security/secret-scanning/introduction/supported-secret-scanning-patterns#supported-secrets)\" for a complete list of secret types.")), + mcp.WithString("resolution", mcp.Description("A comma-separated list of resolutions. Only secret scanning alerts with one of these resolutions are listed. Valid resolutions are `false_positive`, `wont_fix`, `revoked`, `pattern_edited`, `pattern_deleted` or `used_in_tests`.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by. `created` means when the alert was created. `updated` means when the alert was updated or resolved.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for events before this cursor. To receive an initial cursor on your first request, include an empty \"before\" query string.")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for events after this cursor. To receive an initial cursor on your first request, include an empty \"after\" query string.")), + mcp.WithString("validity", mcp.Description("A comma-separated list of validities that, when present, will return alerts that match the validities in this list. Valid options are `active`, `inactive`, and `unknown`.")), + mcp.WithBoolean("is_publicly_leaked", mcp.Description("A boolean value representing whether or not to filter alerts by the publicly-leaked tag being present.")), + mcp.WithBoolean("is_multi_repo", mcp.Description("A boolean value representing whether or not to filter alerts by the multi-repo tag being present.")), + mcp.WithBoolean("hide_secret", mcp.Description("A boolean value representing whether or not to hide literal secrets in the results.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_list_alerts_for_repoHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_list_locations_for_alert.go b/MCP/tools/secret_scanning/secret_scanning_list_locations_for_alert.go new file mode 100644 index 0000000..836f6be --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_list_locations_for_alert.go @@ -0,0 +1,109 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_list_locations_for_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/secret-scanning/alerts/%s/locations%s", cfg.BaseURL, owner, repo, alert_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_list_locations_for_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_secret-scanning_alerts_alert_number_locations", + mcp.WithDescription("List locations for a secret scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_list_locations_for_alertHandler(cfg), + } +} diff --git a/MCP/tools/secret_scanning/secret_scanning_update_alert.go b/MCP/tools/secret_scanning/secret_scanning_update_alert.go new file mode 100644 index 0000000..f59b113 --- /dev/null +++ b/MCP/tools/secret_scanning/secret_scanning_update_alert.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Secret_scanning_update_alertHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + alert_numberVal, ok := args["alert_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: alert_number"), nil + } + alert_number, ok := alert_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: alert_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/secret-scanning/alerts/%s", cfg.BaseURL, owner, repo, alert_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecret_scanning_update_alertTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_secret-scanning_alerts_alert_number", + mcp.WithDescription("Update a secret scanning alert"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithNumber("alert_number", mcp.Required(), mcp.Description("The number that identifies an alert. You can find this at the end of the URL for a code scanning alert within GitHub, and in the `number` field in the response from the `GET /repos/{owner}/{repo}/code-scanning/alerts` operation.")), + mcp.WithString("resolution", mcp.Description("Input parameter: **Required when the `state` is `resolved`.** The reason for resolving the alert.")), + mcp.WithString("resolution_comment", mcp.Description("Input parameter: An optional comment when closing or reopening an alert. Cannot be updated or deleted.")), + mcp.WithString("state", mcp.Required(), mcp.Description("Input parameter: Sets the state of the secret scanning alert. You must provide `resolution` when you set the state to `resolved`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Secret_scanning_update_alertHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_create_fork.go b/MCP/tools/security_advisories/security_advisories_create_fork.go new file mode 100644 index 0000000..2619225 --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_create_fork.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_create_forkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ghsa_idVal, ok := args["ghsa_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ghsa_id"), nil + } + ghsa_id, ok := ghsa_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ghsa_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories/%s/forks", cfg.BaseURL, owner, repo, ghsa_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_create_forkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_security-advisories_ghsa_id_forks", + mcp.WithDescription("Create a temporary private fork"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ghsa_id", mcp.Required(), mcp.Description("The GHSA (GitHub Security Advisory) identifier of the advisory.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_create_forkHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_create_private_vulnerability_report.go b/MCP/tools/security_advisories/security_advisories_create_private_vulnerability_report.go new file mode 100644 index 0000000..972117b --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_create_private_vulnerability_report.go @@ -0,0 +1,111 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_create_private_vulnerability_reportHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories/reports", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_create_private_vulnerability_reportTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_security-advisories_reports", + mcp.WithDescription("Privately report a security vulnerability"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("description", mcp.Required(), mcp.Description("Input parameter: A detailed description of what the advisory impacts.")), + mcp.WithString("severity", mcp.Description("Input parameter: The severity of the advisory. You must choose between setting this field or `cvss_vector_string`.")), + mcp.WithBoolean("start_private_fork", mcp.Description("Input parameter: Whether to create a temporary private fork of the repository to collaborate on a fix.")), + mcp.WithString("summary", mcp.Required(), mcp.Description("Input parameter: A short summary of the advisory.")), + mcp.WithArray("vulnerabilities", mcp.Description("Input parameter: An array of products affected by the vulnerability detailed in a repository security advisory.")), + mcp.WithString("cvss_vector_string", mcp.Description("Input parameter: The CVSS vector that calculates the severity of the advisory. You must choose between setting this field or `severity`.")), + mcp.WithArray("cwe_ids", mcp.Description("Input parameter: A list of Common Weakness Enumeration (CWE) IDs.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_create_private_vulnerability_reportHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_create_repository_advisory.go b/MCP/tools/security_advisories/security_advisories_create_repository_advisory.go new file mode 100644 index 0000000..1364fab --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_create_repository_advisory.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_create_repository_advisoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories", cfg.BaseURL, owner, repo) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_create_repository_advisoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_security-advisories", + mcp.WithDescription("Create a repository security advisory"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("summary", mcp.Required(), mcp.Description("Input parameter: A short summary of the advisory.")), + mcp.WithArray("vulnerabilities", mcp.Required(), mcp.Description("Input parameter: A product affected by the vulnerability detailed in a repository security advisory.")), + mcp.WithString("cvss_vector_string", mcp.Description("Input parameter: The CVSS vector that calculates the severity of the advisory. You must choose between setting this field or `severity`.")), + mcp.WithString("description", mcp.Required(), mcp.Description("Input parameter: A detailed description of what the advisory impacts.")), + mcp.WithString("severity", mcp.Description("Input parameter: The severity of the advisory. You must choose between setting this field or `cvss_vector_string`.")), + mcp.WithString("cve_id", mcp.Description("Input parameter: The Common Vulnerabilities and Exposures (CVE) ID.")), + mcp.WithArray("cwe_ids", mcp.Description("Input parameter: A list of Common Weakness Enumeration (CWE) IDs.")), + mcp.WithBoolean("start_private_fork", mcp.Description("Input parameter: Whether to create a temporary private fork of the repository to collaborate on a fix.")), + mcp.WithArray("credits", mcp.Description("Input parameter: A list of users receiving credit for their participation in the security advisory.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_create_repository_advisoryHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_create_repository_advisory_cve_request.go b/MCP/tools/security_advisories/security_advisories_create_repository_advisory_cve_request.go new file mode 100644 index 0000000..ffbac48 --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_create_repository_advisory_cve_request.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_create_repository_advisory_cve_requestHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ghsa_idVal, ok := args["ghsa_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ghsa_id"), nil + } + ghsa_id, ok := ghsa_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ghsa_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories/%s/cve", cfg.BaseURL, owner, repo, ghsa_id) + req, err := http.NewRequest("POST", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_create_repository_advisory_cve_requestTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_repos_owner_repo_security-advisories_ghsa_id_cve", + mcp.WithDescription("Request a CVE for a repository security advisory"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ghsa_id", mcp.Required(), mcp.Description("The GHSA (GitHub Security Advisory) identifier of the advisory.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_create_repository_advisory_cve_requestHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_get_global_advisory.go b/MCP/tools/security_advisories/security_advisories_get_global_advisory.go new file mode 100644 index 0000000..653fbcd --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_get_global_advisory.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_get_global_advisoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ghsa_idVal, ok := args["ghsa_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ghsa_id"), nil + } + ghsa_id, ok := ghsa_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ghsa_id"), nil + } + url := fmt.Sprintf("%s/advisories/%s", cfg.BaseURL, ghsa_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_get_global_advisoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_advisories_ghsa_id", + mcp.WithDescription("Get a global security advisory"), + mcp.WithString("ghsa_id", mcp.Required(), mcp.Description("The GHSA (GitHub Security Advisory) identifier of the advisory.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_get_global_advisoryHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_get_repository_advisory.go b/MCP/tools/security_advisories/security_advisories_get_repository_advisory.go new file mode 100644 index 0000000..43abc39 --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_get_repository_advisory.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_get_repository_advisoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ghsa_idVal, ok := args["ghsa_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ghsa_id"), nil + } + ghsa_id, ok := ghsa_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ghsa_id"), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories/%s", cfg.BaseURL, owner, repo, ghsa_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_get_repository_advisoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_security-advisories_ghsa_id", + mcp.WithDescription("Get a repository security advisory"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ghsa_id", mcp.Required(), mcp.Description("The GHSA (GitHub Security Advisory) identifier of the advisory.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_get_repository_advisoryHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_list_global_advisories.go b/MCP/tools/security_advisories/security_advisories_list_global_advisories.go new file mode 100644 index 0000000..3f62664 --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_list_global_advisories.go @@ -0,0 +1,146 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_list_global_advisoriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["ghsa_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ghsa_id=%v", val)) + } + if val, ok := args["type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("type=%v", val)) + } + if val, ok := args["cve_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("cve_id=%v", val)) + } + if val, ok := args["ecosystem"]; ok { + queryParams = append(queryParams, fmt.Sprintf("ecosystem=%v", val)) + } + if val, ok := args["severity"]; ok { + queryParams = append(queryParams, fmt.Sprintf("severity=%v", val)) + } + if val, ok := args["cwes"]; ok { + queryParams = append(queryParams, fmt.Sprintf("cwes=%v", val)) + } + if val, ok := args["is_withdrawn"]; ok { + queryParams = append(queryParams, fmt.Sprintf("is_withdrawn=%v", val)) + } + if val, ok := args["affects"]; ok { + queryParams = append(queryParams, fmt.Sprintf("affects=%v", val)) + } + if val, ok := args["published"]; ok { + queryParams = append(queryParams, fmt.Sprintf("published=%v", val)) + } + if val, ok := args["updated"]; ok { + queryParams = append(queryParams, fmt.Sprintf("updated=%v", val)) + } + if val, ok := args["modified"]; ok { + queryParams = append(queryParams, fmt.Sprintf("modified=%v", val)) + } + if val, ok := args["epss_percentage"]; ok { + queryParams = append(queryParams, fmt.Sprintf("epss_percentage=%v", val)) + } + if val, ok := args["epss_percentile"]; ok { + queryParams = append(queryParams, fmt.Sprintf("epss_percentile=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/advisories%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_list_global_advisoriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_advisories", + mcp.WithDescription("List global security advisories"), + mcp.WithString("ghsa_id", mcp.Description("If specified, only advisories with this GHSA (GitHub Security Advisory) identifier will be returned.")), + mcp.WithString("type", mcp.Description("If specified, only advisories of this type will be returned. By default, a request with no other parameters defined will only return reviewed advisories that are not malware.")), + mcp.WithString("cve_id", mcp.Description("If specified, only advisories with this CVE (Common Vulnerabilities and Exposures) identifier will be returned.")), + mcp.WithString("ecosystem", mcp.Description("If specified, only advisories for these ecosystems will be returned.")), + mcp.WithString("severity", mcp.Description("If specified, only advisories with these severities will be returned.")), + mcp.WithString("cwes", mcp.Description("If specified, only advisories with these Common Weakness Enumerations (CWEs) will be returned.\n\nExample: `cwes=79,284,22` or `cwes[]=79&cwes[]=284&cwes[]=22`")), + mcp.WithBoolean("is_withdrawn", mcp.Description("Whether to only return advisories that have been withdrawn.")), + mcp.WithString("affects", mcp.Description("If specified, only return advisories that affect any of `package` or `package@version`. A maximum of 1000 packages can be specified.\nIf the query parameter causes the URL to exceed the maximum URL length supported by your client, you must specify fewer packages.\n\nExample: `affects=package1,package2@1.0.0,package3@^2.0.0` or `affects[]=package1&affects[]=package2@1.0.0`")), + mcp.WithString("published", mcp.Description("If specified, only return advisories that were published on a date or date range.\n\nFor more information on the syntax of the date range, see \"[Understanding the search syntax](https://docs.github.com/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates).\"")), + mcp.WithString("updated", mcp.Description("If specified, only return advisories that were updated on a date or date range.\n\nFor more information on the syntax of the date range, see \"[Understanding the search syntax](https://docs.github.com/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates).\"")), + mcp.WithString("modified", mcp.Description("If specified, only show advisories that were updated or published on a date or date range.\n\nFor more information on the syntax of the date range, see \"[Understanding the search syntax](https://docs.github.com/search-github/getting-started-with-searching-on-github/understanding-the-search-syntax#query-for-dates).\"")), + mcp.WithString("epss_percentage", mcp.Description("If specified, only return advisories that have an EPSS percentage score that matches the provided value.\nThe EPSS percentage represents the likelihood of a CVE being exploited.")), + mcp.WithString("epss_percentile", mcp.Description("If specified, only return advisories that have an EPSS percentile score that matches the provided value.\nThe EPSS percentile represents the relative rank of the CVE's likelihood of being exploited compared to other CVEs.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_list_global_advisoriesHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_list_org_repository_advisories.go b/MCP/tools/security_advisories/security_advisories_list_org_repository_advisories.go new file mode 100644 index 0000000..01aadca --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_list_org_repository_advisories.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_list_org_repository_advisoriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/security-advisories%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_list_org_repository_advisoriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_security-advisories", + mcp.WithDescription("List repository security advisories for an organization"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of advisories to return per page. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("state", mcp.Description("Filter by the state of the repository advisories. Only advisories of this state will be returned.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_list_org_repository_advisoriesHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_list_repository_advisories.go b/MCP/tools/security_advisories/security_advisories_list_repository_advisories.go new file mode 100644 index 0000000..b9bf3c7 --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_list_repository_advisories.go @@ -0,0 +1,116 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_list_repository_advisoriesHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["sort"]; ok { + queryParams = append(queryParams, fmt.Sprintf("sort=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["state"]; ok { + queryParams = append(queryParams, fmt.Sprintf("state=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories%s", cfg.BaseURL, owner, repo, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_list_repository_advisoriesTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_repos_owner_repo_security-advisories", + mcp.WithDescription("List repository security advisories"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithString("sort", mcp.Description("The property to sort the results by.")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("per_page", mcp.Description("The number of advisories to return per page. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("state", mcp.Description("Filter by state of the repository advisories. Only advisories of this state will be returned.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_list_repository_advisoriesHandler(cfg), + } +} diff --git a/MCP/tools/security_advisories/security_advisories_update_repository_advisory.go b/MCP/tools/security_advisories/security_advisories_update_repository_advisory.go new file mode 100644 index 0000000..fefdb98 --- /dev/null +++ b/MCP/tools/security_advisories/security_advisories_update_repository_advisory.go @@ -0,0 +1,124 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Security_advisories_update_repository_advisoryHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + ghsa_idVal, ok := args["ghsa_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ghsa_id"), nil + } + ghsa_id, ok := ghsa_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ghsa_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody models.GeneratedType + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/repos/%s/%s/security-advisories/%s", cfg.BaseURL, owner, repo, ghsa_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateSecurity_advisories_update_repository_advisoryTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_repos_owner_repo_security-advisories_ghsa_id", + mcp.WithDescription("Update a repository security advisory"), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("ghsa_id", mcp.Required(), mcp.Description("The GHSA (GitHub Security Advisory) identifier of the advisory.")), + mcp.WithArray("vulnerabilities", mcp.Description("Input parameter: A product affected by the vulnerability detailed in a repository security advisory.")), + mcp.WithArray("collaborating_users", mcp.Description("Input parameter: A list of usernames who have been granted write access to the advisory.")), + mcp.WithArray("credits", mcp.Description("Input parameter: A list of users receiving credit for their participation in the security advisory.")), + mcp.WithString("severity", mcp.Description("Input parameter: The severity of the advisory. You must choose between setting this field or `cvss_vector_string`.")), + mcp.WithString("cve_id", mcp.Description("Input parameter: The Common Vulnerabilities and Exposures (CVE) ID.")), + mcp.WithString("cvss_vector_string", mcp.Description("Input parameter: The CVSS vector that calculates the severity of the advisory. You must choose between setting this field or `severity`.")), + mcp.WithString("description", mcp.Description("Input parameter: A detailed description of what the advisory impacts.")), + mcp.WithString("state", mcp.Description("Input parameter: The state of the advisory.")), + mcp.WithString("summary", mcp.Description("Input parameter: A short summary of the advisory.")), + mcp.WithArray("collaborating_teams", mcp.Description("Input parameter: A list of team slugs which have been granted write access to the advisory.")), + mcp.WithArray("cwe_ids", mcp.Description("Input parameter: A list of Common Weakness Enumeration (CWE) IDs.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Security_advisories_update_repository_advisoryHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_member_legacy.go b/MCP/tools/teams/teams_add_member_legacy.go new file mode 100644 index 0000000..e098a78 --- /dev/null +++ b/MCP/tools/teams/teams_add_member_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_member_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/teams/%s/members/%s", cfg.BaseURL, team_id, username) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_member_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_teams_team_id_members_username", + mcp.WithDescription("Add team member (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_member_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_or_update_membership_for_user_in_org.go b/MCP/tools/teams/teams_add_or_update_membership_for_user_in_org.go new file mode 100644 index 0000000..05fb92a --- /dev/null +++ b/MCP/tools/teams/teams_add_or_update_membership_for_user_in_org.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_or_update_membership_for_user_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/memberships/%s", cfg.BaseURL, org, team_slug, username) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_or_update_membership_for_user_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_teams_team_slug_memberships_username", + mcp.WithDescription("Add or update team membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("role", mcp.Description("Input parameter: The role that this user should have in the team.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_or_update_membership_for_user_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_or_update_membership_for_user_legacy.go b/MCP/tools/teams/teams_add_or_update_membership_for_user_legacy.go new file mode 100644 index 0000000..06aa2f9 --- /dev/null +++ b/MCP/tools/teams/teams_add_or_update_membership_for_user_legacy.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_or_update_membership_for_user_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/memberships/%s", cfg.BaseURL, team_id, username) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_or_update_membership_for_user_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_teams_team_id_memberships_username", + mcp.WithDescription("Add or update team membership for a user (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("role", mcp.Description("Input parameter: The role that this user should have in the team.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_or_update_membership_for_user_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_or_update_project_permissions_in_org.go b/MCP/tools/teams/teams_add_or_update_project_permissions_in_org.go new file mode 100644 index 0000000..e4426cb --- /dev/null +++ b/MCP/tools/teams/teams_add_or_update_project_permissions_in_org.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_or_update_project_permissions_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/projects/%s", cfg.BaseURL, org, team_slug, project_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_or_update_project_permissions_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_teams_team_slug_projects_project_id", + mcp.WithDescription("Add or update team project permissions"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("permission", mcp.Description("Input parameter: The permission to grant to the team for this project. Default: the team's `permission` attribute will be used to determine what permission to grant the team on this project. Note that, if you choose not to pass any parameters, you'll need to set `Content-Length` to zero when calling this endpoint. For more information, see \"[HTTP method](https://docs.github.com/rest/guides/getting-started-with-the-rest-api#http-method).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_or_update_project_permissions_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_or_update_project_permissions_legacy.go b/MCP/tools/teams/teams_add_or_update_project_permissions_legacy.go new file mode 100644 index 0000000..e88aaa1 --- /dev/null +++ b/MCP/tools/teams/teams_add_or_update_project_permissions_legacy.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_or_update_project_permissions_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/projects/%s", cfg.BaseURL, team_id, project_id) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_or_update_project_permissions_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_teams_team_id_projects_project_id", + mcp.WithDescription("Add or update team project permissions (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + mcp.WithString("permission", mcp.Description("Input parameter: The permission to grant to the team for this project. Default: the team's `permission` attribute will be used to determine what permission to grant the team on this project. Note that, if you choose not to pass any parameters, you'll need to set `Content-Length` to zero when calling this endpoint. For more information, see \"[HTTP method](https://docs.github.com/rest/guides/getting-started-with-the-rest-api#http-method).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_or_update_project_permissions_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_or_update_repo_permissions_in_org.go b/MCP/tools/teams/teams_add_or_update_repo_permissions_in_org.go new file mode 100644 index 0000000..892bacb --- /dev/null +++ b/MCP/tools/teams/teams_add_or_update_repo_permissions_in_org.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_or_update_repo_permissions_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/repos/%s/%s", cfg.BaseURL, org, team_slug, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_or_update_repo_permissions_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_orgs_org_teams_team_slug_repos_owner_repo", + mcp.WithDescription("Add or update team repository permissions"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("permission", mcp.Description("Input parameter: The permission to grant the team on this repository. We accept the following permissions to be set: `pull`, `triage`, `push`, `maintain`, `admin` and you can also specify a custom repository role name, if the owning organization has defined any. If no permission is specified, the team's `permission` attribute will be used to determine what permission to grant the team on this repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_or_update_repo_permissions_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_add_or_update_repo_permissions_legacy.go b/MCP/tools/teams/teams_add_or_update_repo_permissions_legacy.go new file mode 100644 index 0000000..d8dd4cb --- /dev/null +++ b/MCP/tools/teams/teams_add_or_update_repo_permissions_legacy.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_add_or_update_repo_permissions_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/repos/%s/%s", cfg.BaseURL, team_id, owner, repo) + req, err := http.NewRequest("PUT", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_add_or_update_repo_permissions_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_teams_team_id_repos_owner_repo", + mcp.WithDescription("Add or update team repository permissions (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + mcp.WithString("permission", mcp.Description("Input parameter: The permission to grant the team on this repository. If no permission is specified, the team's `permission` attribute will be used to determine what permission to grant the team on this repository.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_add_or_update_repo_permissions_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_check_permissions_for_project_in_org.go b/MCP/tools/teams/teams_check_permissions_for_project_in_org.go new file mode 100644 index 0000000..6328cf7 --- /dev/null +++ b/MCP/tools/teams/teams_check_permissions_for_project_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_check_permissions_for_project_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/projects/%s", cfg.BaseURL, org, team_slug, project_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_check_permissions_for_project_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_projects_project_id", + mcp.WithDescription("Check team permissions for a project"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_check_permissions_for_project_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_check_permissions_for_project_legacy.go b/MCP/tools/teams/teams_check_permissions_for_project_legacy.go new file mode 100644 index 0000000..79028e2 --- /dev/null +++ b/MCP/tools/teams/teams_check_permissions_for_project_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_check_permissions_for_project_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + url := fmt.Sprintf("%s/teams/%s/projects/%s", cfg.BaseURL, team_id, project_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_check_permissions_for_project_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_projects_project_id", + mcp.WithDescription("Check team permissions for a project (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_check_permissions_for_project_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_check_permissions_for_repo_in_org.go b/MCP/tools/teams/teams_check_permissions_for_repo_in_org.go new file mode 100644 index 0000000..fca2261 --- /dev/null +++ b/MCP/tools/teams/teams_check_permissions_for_repo_in_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_check_permissions_for_repo_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/repos/%s/%s", cfg.BaseURL, org, team_slug, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_check_permissions_for_repo_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_repos_owner_repo", + mcp.WithDescription("Check team permissions for a repository"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_check_permissions_for_repo_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_check_permissions_for_repo_legacy.go b/MCP/tools/teams/teams_check_permissions_for_repo_legacy.go new file mode 100644 index 0000000..c5479b2 --- /dev/null +++ b/MCP/tools/teams/teams_check_permissions_for_repo_legacy.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_check_permissions_for_repo_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/teams/%s/repos/%s/%s", cfg.BaseURL, team_id, owner, repo) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_check_permissions_for_repo_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_repos_owner_repo", + mcp.WithDescription("Check team permissions for a repository (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_check_permissions_for_repo_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_create.go b/MCP/tools/teams/teams_create.go new file mode 100644 index 0000000..fcbecbe --- /dev/null +++ b/MCP/tools/teams/teams_create.go @@ -0,0 +1,103 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_createHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams", cfg.BaseURL, org) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_createTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_teams", + mcp.WithDescription("Create a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("privacy", mcp.Description("Input parameter: The level of privacy this team should have. The options are: \n**For a non-nested team:** \n * `secret` - only visible to organization owners and members of this team. \n * `closed` - visible to all members of this organization. \nDefault: `secret` \n**For a parent or child team:** \n * `closed` - visible to all members of this organization. \nDefault for child team: `closed`")), + mcp.WithArray("repo_names", mcp.Description("Input parameter: The full name (e.g., \"organization-name/repository-name\") of repositories to add the team to.")), + mcp.WithString("description", mcp.Description("Input parameter: The description of the team.")), + mcp.WithArray("maintainers", mcp.Description("Input parameter: List GitHub usernames for organization members who will become team maintainers.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the team.")), + mcp.WithString("notification_setting", mcp.Description("Input parameter: The notification setting the team has chosen. The options are: \n * `notifications_enabled` - team members receive notifications when the team is @mentioned. \n * `notifications_disabled` - no one receives notifications. \nDefault: `notifications_enabled`")), + mcp.WithNumber("parent_team_id", mcp.Description("Input parameter: The ID of a team to set as the parent team.")), + mcp.WithString("permission", mcp.Description("Input parameter: **Closing down notice**. The permission that new repositories will be added to the team with when none is specified.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_createHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_create_discussion_comment_in_org.go b/MCP/tools/teams/teams_create_discussion_comment_in_org.go new file mode 100644 index 0000000..3393001 --- /dev/null +++ b/MCP/tools/teams/teams_create_discussion_comment_in_org.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_create_discussion_comment_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments", cfg.BaseURL, org, team_slug, discussion_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_create_discussion_comment_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_teams_team_slug_discussions_discussion_number_comments", + mcp.WithDescription("Create a discussion comment"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The discussion comment's body text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_create_discussion_comment_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_create_discussion_comment_legacy.go b/MCP/tools/teams/teams_create_discussion_comment_legacy.go new file mode 100644 index 0000000..98fcf1b --- /dev/null +++ b/MCP/tools/teams/teams_create_discussion_comment_legacy.go @@ -0,0 +1,105 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_create_discussion_comment_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments", cfg.BaseURL, team_id, discussion_number) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_create_discussion_comment_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_teams_team_id_discussions_discussion_number_comments", + mcp.WithDescription("Create a discussion comment (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The discussion comment's body text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_create_discussion_comment_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_create_discussion_in_org.go b/MCP/tools/teams/teams_create_discussion_in_org.go new file mode 100644 index 0000000..a11c09c --- /dev/null +++ b/MCP/tools/teams/teams_create_discussion_in_org.go @@ -0,0 +1,107 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_create_discussion_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_create_discussion_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_orgs_org_teams_team_slug_discussions", + mcp.WithDescription("Create a discussion"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The discussion post's body text.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Private posts are only visible to team members, organization owners, and team maintainers. Public posts are visible to all members of the organization. Set to `true` to create a private post.")), + mcp.WithString("title", mcp.Required(), mcp.Description("Input parameter: The discussion post's title.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_create_discussion_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_create_discussion_legacy.go b/MCP/tools/teams/teams_create_discussion_legacy.go new file mode 100644 index 0000000..15569e0 --- /dev/null +++ b/MCP/tools/teams/teams_create_discussion_legacy.go @@ -0,0 +1,98 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_create_discussion_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions", cfg.BaseURL, team_id) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_create_discussion_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_teams_team_id_discussions", + mcp.WithDescription("Create a discussion (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("title", mcp.Required(), mcp.Description("Input parameter: The discussion post's title.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The discussion post's body text.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Private posts are only visible to team members, organization owners, and team maintainers. Public posts are visible to all members of the organization. Set to `true` to create a private post.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_create_discussion_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_delete_discussion_comment_in_org.go b/MCP/tools/teams/teams_delete_discussion_comment_in_org.go new file mode 100644 index 0000000..a3350a0 --- /dev/null +++ b/MCP/tools/teams/teams_delete_discussion_comment_in_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_delete_discussion_comment_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments/%s", cfg.BaseURL, org, team_slug, discussion_number, comment_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_delete_discussion_comment_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_discussions_discussion_number_comments_comment_number", + mcp.WithDescription("Delete a discussion comment"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_delete_discussion_comment_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_delete_discussion_comment_legacy.go b/MCP/tools/teams/teams_delete_discussion_comment_legacy.go new file mode 100644 index 0000000..a97109d --- /dev/null +++ b/MCP/tools/teams/teams_delete_discussion_comment_legacy.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_delete_discussion_comment_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments/%s", cfg.BaseURL, team_id, discussion_number, comment_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_delete_discussion_comment_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id_discussions_discussion_number_comments_comment_number", + mcp.WithDescription("Delete a discussion comment (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_delete_discussion_comment_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_delete_discussion_in_org.go b/MCP/tools/teams/teams_delete_discussion_in_org.go new file mode 100644 index 0000000..972e649 --- /dev/null +++ b/MCP/tools/teams/teams_delete_discussion_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_delete_discussion_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s", cfg.BaseURL, org, team_slug, discussion_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_delete_discussion_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_discussions_discussion_number", + mcp.WithDescription("Delete a discussion"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_delete_discussion_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_delete_discussion_legacy.go b/MCP/tools/teams/teams_delete_discussion_legacy.go new file mode 100644 index 0000000..69790b4 --- /dev/null +++ b/MCP/tools/teams/teams_delete_discussion_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_delete_discussion_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s", cfg.BaseURL, team_id, discussion_number) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_delete_discussion_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id_discussions_discussion_number", + mcp.WithDescription("Delete a discussion (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_delete_discussion_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_delete_in_org.go b/MCP/tools/teams/teams_delete_in_org.go new file mode 100644 index 0000000..761e719 --- /dev/null +++ b/MCP/tools/teams/teams_delete_in_org.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_delete_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_delete_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug", + mcp.WithDescription("Delete a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_delete_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_delete_legacy.go b/MCP/tools/teams/teams_delete_legacy.go new file mode 100644 index 0000000..215d279 --- /dev/null +++ b/MCP/tools/teams/teams_delete_legacy.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_delete_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + url := fmt.Sprintf("%s/teams/%s", cfg.BaseURL, team_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_delete_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id", + mcp.WithDescription("Delete a team (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_delete_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_by_name.go b/MCP/tools/teams/teams_get_by_name.go new file mode 100644 index 0000000..78c4d72 --- /dev/null +++ b/MCP/tools/teams/teams_get_by_name.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_by_nameHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_by_nameTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug", + mcp.WithDescription("Get a team by name"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_by_nameHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_discussion_comment_in_org.go b/MCP/tools/teams/teams_get_discussion_comment_in_org.go new file mode 100644 index 0000000..42f579d --- /dev/null +++ b/MCP/tools/teams/teams_get_discussion_comment_in_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_discussion_comment_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments/%s", cfg.BaseURL, org, team_slug, discussion_number, comment_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_discussion_comment_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_discussions_discussion_number_comments_comment_number", + mcp.WithDescription("Get a discussion comment"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_discussion_comment_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_discussion_comment_legacy.go b/MCP/tools/teams/teams_get_discussion_comment_legacy.go new file mode 100644 index 0000000..e013218 --- /dev/null +++ b/MCP/tools/teams/teams_get_discussion_comment_legacy.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_discussion_comment_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments/%s", cfg.BaseURL, team_id, discussion_number, comment_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_discussion_comment_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_discussions_discussion_number_comments_comment_number", + mcp.WithDescription("Get a discussion comment (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_discussion_comment_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_discussion_in_org.go b/MCP/tools/teams/teams_get_discussion_in_org.go new file mode 100644 index 0000000..10814ed --- /dev/null +++ b/MCP/tools/teams/teams_get_discussion_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_discussion_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s", cfg.BaseURL, org, team_slug, discussion_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_discussion_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_discussions_discussion_number", + mcp.WithDescription("Get a discussion"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_discussion_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_discussion_legacy.go b/MCP/tools/teams/teams_get_discussion_legacy.go new file mode 100644 index 0000000..ae9e15e --- /dev/null +++ b/MCP/tools/teams/teams_get_discussion_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_discussion_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s", cfg.BaseURL, team_id, discussion_number) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_discussion_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_discussions_discussion_number", + mcp.WithDescription("Get a discussion (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_discussion_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_legacy.go b/MCP/tools/teams/teams_get_legacy.go new file mode 100644 index 0000000..22917d0 --- /dev/null +++ b/MCP/tools/teams/teams_get_legacy.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + url := fmt.Sprintf("%s/teams/%s", cfg.BaseURL, team_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id", + mcp.WithDescription("Get a team (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_member_legacy.go b/MCP/tools/teams/teams_get_member_legacy.go new file mode 100644 index 0000000..a30ea79 --- /dev/null +++ b/MCP/tools/teams/teams_get_member_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_member_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/teams/%s/members/%s", cfg.BaseURL, team_id, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_member_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_members_username", + mcp.WithDescription("Get team member (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_member_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_membership_for_user_in_org.go b/MCP/tools/teams/teams_get_membership_for_user_in_org.go new file mode 100644 index 0000000..b080a17 --- /dev/null +++ b/MCP/tools/teams/teams_get_membership_for_user_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_membership_for_user_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/memberships/%s", cfg.BaseURL, org, team_slug, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_membership_for_user_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_memberships_username", + mcp.WithDescription("Get team membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_membership_for_user_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_get_membership_for_user_legacy.go b/MCP/tools/teams/teams_get_membership_for_user_legacy.go new file mode 100644 index 0000000..8e31040 --- /dev/null +++ b/MCP/tools/teams/teams_get_membership_for_user_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_get_membership_for_user_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/teams/%s/memberships/%s", cfg.BaseURL, team_id, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_get_membership_for_user_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_memberships_username", + mcp.WithDescription("Get team membership for a user (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_get_membership_for_user_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list.go b/MCP/tools/teams/teams_list.go new file mode 100644 index 0000000..02d9e18 --- /dev/null +++ b/MCP/tools/teams/teams_list.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams%s", cfg.BaseURL, org, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams", + mcp.WithDescription("List teams"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_listHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_child_in_org.go b/MCP/tools/teams/teams_list_child_in_org.go new file mode 100644 index 0000000..b749a05 --- /dev/null +++ b/MCP/tools/teams/teams_list_child_in_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_child_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/teams%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_child_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_teams", + mcp.WithDescription("List child teams"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_child_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_child_legacy.go b/MCP/tools/teams/teams_list_child_legacy.go new file mode 100644 index 0000000..457d8aa --- /dev/null +++ b/MCP/tools/teams/teams_list_child_legacy.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_child_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/teams%s", cfg.BaseURL, team_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Team + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_child_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_teams", + mcp.WithDescription("List child teams (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_child_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_discussion_comments_in_org.go b/MCP/tools/teams/teams_list_discussion_comments_in_org.go new file mode 100644 index 0000000..7ff9a72 --- /dev/null +++ b/MCP/tools/teams/teams_list_discussion_comments_in_org.go @@ -0,0 +1,113 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_discussion_comments_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments%s", cfg.BaseURL, org, team_slug, discussion_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_discussion_comments_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_discussions_discussion_number_comments", + mcp.WithDescription("List discussion comments"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_discussion_comments_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_discussion_comments_legacy.go b/MCP/tools/teams/teams_list_discussion_comments_legacy.go new file mode 100644 index 0000000..f75bfca --- /dev/null +++ b/MCP/tools/teams/teams_list_discussion_comments_legacy.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_discussion_comments_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments%s", cfg.BaseURL, team_id, discussion_number, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_discussion_comments_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_discussions_discussion_number_comments", + mcp.WithDescription("List discussion comments (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_discussion_comments_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_discussions_in_org.go b/MCP/tools/teams/teams_list_discussions_in_org.go new file mode 100644 index 0000000..e56d036 --- /dev/null +++ b/MCP/tools/teams/teams_list_discussions_in_org.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_discussions_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + if val, ok := args["pinned"]; ok { + queryParams = append(queryParams, fmt.Sprintf("pinned=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_discussions_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_discussions", + mcp.WithDescription("List discussions"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("pinned", mcp.Description("Pinned discussions only filter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_discussions_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_discussions_legacy.go b/MCP/tools/teams/teams_list_discussions_legacy.go new file mode 100644 index 0000000..5977a4f --- /dev/null +++ b/MCP/tools/teams/teams_list_discussions_legacy.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_discussions_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["direction"]; ok { + queryParams = append(queryParams, fmt.Sprintf("direction=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/discussions%s", cfg.BaseURL, team_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_discussions_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_discussions", + mcp.WithDescription("List discussions (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("direction", mcp.Description("The direction to sort the results by.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_discussions_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_for_authenticated_user.go b/MCP/tools/teams/teams_list_for_authenticated_user.go new file mode 100644 index 0000000..bfde89b --- /dev/null +++ b/MCP/tools/teams/teams_list_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/teams%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_teams", + mcp.WithDescription("List teams for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_members_in_org.go b/MCP/tools/teams/teams_list_members_in_org.go new file mode 100644 index 0000000..46b29e9 --- /dev/null +++ b/MCP/tools/teams/teams_list_members_in_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_members_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["role"]; ok { + queryParams = append(queryParams, fmt.Sprintf("role=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/members%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_members_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_members", + mcp.WithDescription("List team members"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("role", mcp.Description("Filters members returned by their role in the team.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_members_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_members_legacy.go b/MCP/tools/teams/teams_list_members_legacy.go new file mode 100644 index 0000000..1a9c808 --- /dev/null +++ b/MCP/tools/teams/teams_list_members_legacy.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_members_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["role"]; ok { + queryParams = append(queryParams, fmt.Sprintf("role=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/members%s", cfg.BaseURL, team_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_members_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_members", + mcp.WithDescription("List team members (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("role", mcp.Description("Filters members returned by their role in the team.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_members_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_pending_invitations_in_org.go b/MCP/tools/teams/teams_list_pending_invitations_in_org.go new file mode 100644 index 0000000..d7c0ada --- /dev/null +++ b/MCP/tools/teams/teams_list_pending_invitations_in_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_pending_invitations_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/invitations%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_pending_invitations_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_invitations", + mcp.WithDescription("List pending team invitations"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_pending_invitations_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_pending_invitations_legacy.go b/MCP/tools/teams/teams_list_pending_invitations_legacy.go new file mode 100644 index 0000000..62cb029 --- /dev/null +++ b/MCP/tools/teams/teams_list_pending_invitations_legacy.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_pending_invitations_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/invitations%s", cfg.BaseURL, team_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_pending_invitations_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_invitations", + mcp.WithDescription("List pending team invitations (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_pending_invitations_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_projects_in_org.go b/MCP/tools/teams/teams_list_projects_in_org.go new file mode 100644 index 0000000..16d608f --- /dev/null +++ b/MCP/tools/teams/teams_list_projects_in_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_projects_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/projects%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_projects_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_projects", + mcp.WithDescription("List team projects"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_projects_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_projects_legacy.go b/MCP/tools/teams/teams_list_projects_legacy.go new file mode 100644 index 0000000..a54b977 --- /dev/null +++ b/MCP/tools/teams/teams_list_projects_legacy.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_projects_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/projects%s", cfg.BaseURL, team_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_projects_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_projects", + mcp.WithDescription("List team projects (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_projects_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_repos_in_org.go b/MCP/tools/teams/teams_list_repos_in_org.go new file mode 100644 index 0000000..5e0a0d9 --- /dev/null +++ b/MCP/tools/teams/teams_list_repos_in_org.go @@ -0,0 +1,100 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_repos_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/repos%s", cfg.BaseURL, org, team_slug, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_repos_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_orgs_org_teams_team_slug_repos", + mcp.WithDescription("List team repositories"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_repos_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_list_repos_legacy.go b/MCP/tools/teams/teams_list_repos_legacy.go new file mode 100644 index 0000000..b8b2b98 --- /dev/null +++ b/MCP/tools/teams/teams_list_repos_legacy.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_list_repos_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/teams/%s/repos%s", cfg.BaseURL, team_id, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_list_repos_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_teams_team_id_repos", + mcp.WithDescription("List team repositories (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_list_repos_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_member_legacy.go b/MCP/tools/teams/teams_remove_member_legacy.go new file mode 100644 index 0000000..8e87078 --- /dev/null +++ b/MCP/tools/teams/teams_remove_member_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_member_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/teams/%s/members/%s", cfg.BaseURL, team_id, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_member_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id_members_username", + mcp.WithDescription("Remove team member (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_member_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_membership_for_user_in_org.go b/MCP/tools/teams/teams_remove_membership_for_user_in_org.go new file mode 100644 index 0000000..68535e1 --- /dev/null +++ b/MCP/tools/teams/teams_remove_membership_for_user_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_membership_for_user_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/memberships/%s", cfg.BaseURL, org, team_slug, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_membership_for_user_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_memberships_username", + mcp.WithDescription("Remove team membership for a user"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_membership_for_user_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_membership_for_user_legacy.go b/MCP/tools/teams/teams_remove_membership_for_user_legacy.go new file mode 100644 index 0000000..569c3ba --- /dev/null +++ b/MCP/tools/teams/teams_remove_membership_for_user_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_membership_for_user_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/teams/%s/memberships/%s", cfg.BaseURL, team_id, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_membership_for_user_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id_memberships_username", + mcp.WithDescription("Remove team membership for a user (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_membership_for_user_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_project_in_org.go b/MCP/tools/teams/teams_remove_project_in_org.go new file mode 100644 index 0000000..42488a9 --- /dev/null +++ b/MCP/tools/teams/teams_remove_project_in_org.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_project_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/projects/%s", cfg.BaseURL, org, team_slug, project_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_project_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_projects_project_id", + mcp.WithDescription("Remove a project from a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_project_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_project_legacy.go b/MCP/tools/teams/teams_remove_project_legacy.go new file mode 100644 index 0000000..35c0d5b --- /dev/null +++ b/MCP/tools/teams/teams_remove_project_legacy.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_project_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + project_idVal, ok := args["project_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: project_id"), nil + } + project_id, ok := project_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: project_id"), nil + } + url := fmt.Sprintf("%s/teams/%s/projects/%s", cfg.BaseURL, team_id, project_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_project_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id_projects_project_id", + mcp.WithDescription("Remove a project from a team (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("project_id", mcp.Required(), mcp.Description("The unique identifier of the project.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_project_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_repo_in_org.go b/MCP/tools/teams/teams_remove_repo_in_org.go new file mode 100644 index 0000000..367a059 --- /dev/null +++ b/MCP/tools/teams/teams_remove_repo_in_org.go @@ -0,0 +1,104 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_repo_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/repos/%s/%s", cfg.BaseURL, org, team_slug, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_repo_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_orgs_org_teams_team_slug_repos_owner_repo", + mcp.WithDescription("Remove a repository from a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_repo_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_remove_repo_legacy.go b/MCP/tools/teams/teams_remove_repo_legacy.go new file mode 100644 index 0000000..badaa8e --- /dev/null +++ b/MCP/tools/teams/teams_remove_repo_legacy.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_remove_repo_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + ownerVal, ok := args["owner"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: owner"), nil + } + owner, ok := ownerVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: owner"), nil + } + repoVal, ok := args["repo"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: repo"), nil + } + repo, ok := repoVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: repo"), nil + } + url := fmt.Sprintf("%s/teams/%s/repos/%s/%s", cfg.BaseURL, team_id, owner, repo) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_remove_repo_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_teams_team_id_repos_owner_repo", + mcp.WithDescription("Remove a repository from a team (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("owner", mcp.Required(), mcp.Description("The account owner of the repository. The name is not case sensitive.")), + mcp.WithString("repo", mcp.Required(), mcp.Description("The name of the repository without the `.git` extension. The name is not case sensitive.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_remove_repo_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_update_discussion_comment_in_org.go b/MCP/tools/teams/teams_update_discussion_comment_in_org.go new file mode 100644 index 0000000..46e1449 --- /dev/null +++ b/MCP/tools/teams/teams_update_discussion_comment_in_org.go @@ -0,0 +1,123 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_update_discussion_comment_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s/comments/%s", cfg.BaseURL, org, team_slug, discussion_number, comment_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_update_discussion_comment_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_teams_team_slug_discussions_discussion_number_comments_comment_number", + mcp.WithDescription("Update a discussion comment"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The discussion comment's body text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_update_discussion_comment_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_update_discussion_comment_legacy.go b/MCP/tools/teams/teams_update_discussion_comment_legacy.go new file mode 100644 index 0000000..812a407 --- /dev/null +++ b/MCP/tools/teams/teams_update_discussion_comment_legacy.go @@ -0,0 +1,114 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_update_discussion_comment_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + comment_numberVal, ok := args["comment_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: comment_number"), nil + } + comment_number, ok := comment_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: comment_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s/comments/%s", cfg.BaseURL, team_id, discussion_number, comment_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_update_discussion_comment_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_teams_team_id_discussions_discussion_number_comments_comment_number", + mcp.WithDescription("Update a discussion comment (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithNumber("comment_number", mcp.Required(), mcp.Description("The number that identifies the comment.")), + mcp.WithString("body", mcp.Required(), mcp.Description("Input parameter: The discussion comment's body text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_update_discussion_comment_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_update_discussion_in_org.go b/MCP/tools/teams/teams_update_discussion_in_org.go new file mode 100644 index 0000000..f2a80a9 --- /dev/null +++ b/MCP/tools/teams/teams_update_discussion_in_org.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_update_discussion_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s/discussions/%s", cfg.BaseURL, org, team_slug, discussion_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_update_discussion_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_teams_team_slug_discussions_discussion_number", + mcp.WithDescription("Update a discussion"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("title", mcp.Description("Input parameter: The discussion post's title.")), + mcp.WithString("body", mcp.Description("Input parameter: The discussion post's body text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_update_discussion_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_update_discussion_legacy.go b/MCP/tools/teams/teams_update_discussion_legacy.go new file mode 100644 index 0000000..8bda74b --- /dev/null +++ b/MCP/tools/teams/teams_update_discussion_legacy.go @@ -0,0 +1,106 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_update_discussion_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + discussion_numberVal, ok := args["discussion_number"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: discussion_number"), nil + } + discussion_number, ok := discussion_numberVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: discussion_number"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s/discussions/%s", cfg.BaseURL, team_id, discussion_number) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_update_discussion_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_teams_team_id_discussions_discussion_number", + mcp.WithDescription("Update a discussion (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithNumber("discussion_number", mcp.Required(), mcp.Description("The number that identifies the discussion.")), + mcp.WithString("title", mcp.Description("Input parameter: The discussion post's title.")), + mcp.WithString("body", mcp.Description("Input parameter: The discussion post's body text.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_update_discussion_legacyHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_update_in_org.go b/MCP/tools/teams/teams_update_in_org.go new file mode 100644 index 0000000..455a1c5 --- /dev/null +++ b/MCP/tools/teams/teams_update_in_org.go @@ -0,0 +1,110 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_update_in_orgHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + orgVal, ok := args["org"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: org"), nil + } + org, ok := orgVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: org"), nil + } + team_slugVal, ok := args["team_slug"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_slug"), nil + } + team_slug, ok := team_slugVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_slug"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/orgs/%s/teams/%s", cfg.BaseURL, org, team_slug) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_update_in_orgTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_orgs_org_teams_team_slug", + mcp.WithDescription("Update a team"), + mcp.WithString("org", mcp.Required(), mcp.Description("The organization name. The name is not case sensitive.")), + mcp.WithString("team_slug", mcp.Required(), mcp.Description("The slug of the team name.")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the team.")), + mcp.WithString("notification_setting", mcp.Description("Input parameter: The notification setting the team has chosen. Editing teams without specifying this parameter leaves `notification_setting` intact. The options are: \n * `notifications_enabled` - team members receive notifications when the team is @mentioned. \n * `notifications_disabled` - no one receives notifications.")), + mcp.WithNumber("parent_team_id", mcp.Description("Input parameter: The ID of a team to set as the parent team.")), + mcp.WithString("permission", mcp.Description("Input parameter: **Closing down notice**. The permission that new repositories will be added to the team with when none is specified.")), + mcp.WithString("privacy", mcp.Description("Input parameter: The level of privacy this team should have. Editing teams without specifying this parameter leaves `privacy` intact. When a team is nested, the `privacy` for parent teams cannot be `secret`. The options are: \n**For a non-nested team:** \n * `secret` - only visible to organization owners and members of this team. \n * `closed` - visible to all members of this organization. \n**For a parent or child team:** \n * `closed` - visible to all members of this organization.")), + mcp.WithString("description", mcp.Description("Input parameter: The description of the team.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_update_in_orgHandler(cfg), + } +} diff --git a/MCP/tools/teams/teams_update_legacy.go b/MCP/tools/teams/teams_update_legacy.go new file mode 100644 index 0000000..cef7e3e --- /dev/null +++ b/MCP/tools/teams/teams_update_legacy.go @@ -0,0 +1,101 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Teams_update_legacyHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + team_idVal, ok := args["team_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: team_id"), nil + } + team_id, ok := team_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: team_id"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/teams/%s", cfg.BaseURL, team_id) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateTeams_update_legacyTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_teams_team_id", + mcp.WithDescription("Update a team (Legacy)"), + mcp.WithNumber("team_id", mcp.Required(), mcp.Description("The unique identifier of the team.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the team.")), + mcp.WithString("notification_setting", mcp.Description("Input parameter: The notification setting the team has chosen. Editing teams without specifying this parameter leaves `notification_setting` intact. The options are: \n * `notifications_enabled` - team members receive notifications when the team is @mentioned. \n * `notifications_disabled` - no one receives notifications.")), + mcp.WithNumber("parent_team_id", mcp.Description("Input parameter: The ID of a team to set as the parent team.")), + mcp.WithString("permission", mcp.Description("Input parameter: **Closing down notice**. The permission that new repositories will be added to the team with when none is specified.")), + mcp.WithString("privacy", mcp.Description("Input parameter: The level of privacy this team should have. Editing teams without specifying this parameter leaves `privacy` intact. The options are: \n**For a non-nested team:** \n * `secret` - only visible to organization owners and members of this team. \n * `closed` - visible to all members of this organization. \n**For a parent or child team:** \n * `closed` - visible to all members of this organization.")), + mcp.WithString("description", mcp.Description("Input parameter: The description of the team.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Teams_update_legacyHandler(cfg), + } +} diff --git a/MCP/tools/users/users_add_email_for_authenticated_user.go b/MCP/tools/users/users_add_email_for_authenticated_user.go new file mode 100644 index 0000000..4d8fd7b --- /dev/null +++ b/MCP/tools/users/users_add_email_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_add_email_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/emails", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Email + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_add_email_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_emails", + mcp.WithDescription("Add an email address for the authenticated user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_add_email_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_add_social_account_for_authenticated_user.go b/MCP/tools/users/users_add_social_account_for_authenticated_user.go new file mode 100644 index 0000000..556ffaf --- /dev/null +++ b/MCP/tools/users/users_add_social_account_for_authenticated_user.go @@ -0,0 +1,87 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_add_social_account_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/social_accounts", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_add_social_account_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_social_accounts", + mcp.WithDescription("Add social accounts for the authenticated user"), + mcp.WithArray("account_urls", mcp.Required(), mcp.Description("Input parameter: Full URLs for the social media profiles to add.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_add_social_account_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_block.go b/MCP/tools/users/users_block.go new file mode 100644 index 0000000..57abc2d --- /dev/null +++ b/MCP/tools/users/users_block.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_blockHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/user/blocks/%s", cfg.BaseURL, username) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_blockTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_blocks_username", + mcp.WithDescription("Block a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_blockHandler(cfg), + } +} diff --git a/MCP/tools/users/users_check_blocked.go b/MCP/tools/users/users_check_blocked.go new file mode 100644 index 0000000..6287c59 --- /dev/null +++ b/MCP/tools/users/users_check_blocked.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_check_blockedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/user/blocks/%s", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_check_blockedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_blocks_username", + mcp.WithDescription("Check if a user is blocked by the authenticated user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_check_blockedHandler(cfg), + } +} diff --git a/MCP/tools/users/users_check_following_for_user.go b/MCP/tools/users/users_check_following_for_user.go new file mode 100644 index 0000000..a214080 --- /dev/null +++ b/MCP/tools/users/users_check_following_for_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_check_following_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + target_userVal, ok := args["target_user"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: target_user"), nil + } + target_user, ok := target_userVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: target_user"), nil + } + url := fmt.Sprintf("%s/users/%s/following/%s", cfg.BaseURL, username, target_user) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_check_following_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_following_target_user", + mcp.WithDescription("Check if a user follows another user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("target_user", mcp.Required(), mcp.Description("")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_check_following_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_check_person_is_followed_by_authenticated.go b/MCP/tools/users/users_check_person_is_followed_by_authenticated.go new file mode 100644 index 0000000..0f3efe7 --- /dev/null +++ b/MCP/tools/users/users_check_person_is_followed_by_authenticated.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_check_person_is_followed_by_authenticatedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/user/following/%s", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_check_person_is_followed_by_authenticatedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_following_username", + mcp.WithDescription("Check if a person is followed by the authenticated user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_check_person_is_followed_by_authenticatedHandler(cfg), + } +} diff --git a/MCP/tools/users/users_create_gpg_key_for_authenticated_user.go b/MCP/tools/users/users_create_gpg_key_for_authenticated_user.go new file mode 100644 index 0000000..d41b9b1 --- /dev/null +++ b/MCP/tools/users/users_create_gpg_key_for_authenticated_user.go @@ -0,0 +1,88 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_create_gpg_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/gpg_keys", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_create_gpg_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_gpg_keys", + mcp.WithDescription("Create a GPG key for the authenticated user"), + mcp.WithString("armored_public_key", mcp.Required(), mcp.Description("Input parameter: A GPG key in ASCII-armored format.")), + mcp.WithString("name", mcp.Description("Input parameter: A descriptive name for the new key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_create_gpg_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_create_public_ssh_key_for_authenticated_user.go b/MCP/tools/users/users_create_public_ssh_key_for_authenticated_user.go new file mode 100644 index 0000000..cfad8d4 --- /dev/null +++ b/MCP/tools/users/users_create_public_ssh_key_for_authenticated_user.go @@ -0,0 +1,88 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_create_public_ssh_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/keys", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Key + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_create_public_ssh_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_keys", + mcp.WithDescription("Create a public SSH key for the authenticated user"), + mcp.WithString("key", mcp.Required(), mcp.Description("Input parameter: The public SSH key to add to your GitHub account.")), + mcp.WithString("title", mcp.Description("Input parameter: A descriptive name for the new key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_create_public_ssh_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_create_ssh_signing_key_for_authenticated_user.go b/MCP/tools/users/users_create_ssh_signing_key_for_authenticated_user.go new file mode 100644 index 0000000..963a304 --- /dev/null +++ b/MCP/tools/users/users_create_ssh_signing_key_for_authenticated_user.go @@ -0,0 +1,88 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_create_ssh_signing_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/ssh_signing_keys", cfg.BaseURL) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_create_ssh_signing_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_user_ssh_signing_keys", + mcp.WithDescription("Create a SSH signing key for the authenticated user"), + mcp.WithString("key", mcp.Required(), mcp.Description("Input parameter: The public SSH key to add to your GitHub account. For more information, see \"[Checking for existing SSH keys](https://docs.github.com/authentication/connecting-to-github-with-ssh/checking-for-existing-ssh-keys).\"")), + mcp.WithString("title", mcp.Description("Input parameter: A descriptive name for the new key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_create_ssh_signing_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_attestations_bulk.go b/MCP/tools/users/users_delete_attestations_bulk.go new file mode 100644 index 0000000..92378f9 --- /dev/null +++ b/MCP/tools/users/users_delete_attestations_bulk.go @@ -0,0 +1,95 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_attestations_bulkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/users/%s/attestations/delete-request", cfg.BaseURL, username) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_attestations_bulkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_users_username_attestations_delete-request", + mcp.WithDescription("Delete attestations in bulk"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_attestations_bulkHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_attestations_by_id.go b/MCP/tools/users/users_delete_attestations_by_id.go new file mode 100644 index 0000000..d950c5a --- /dev/null +++ b/MCP/tools/users/users_delete_attestations_by_id.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_attestations_by_idHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + attestation_idVal, ok := args["attestation_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: attestation_id"), nil + } + attestation_id, ok := attestation_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: attestation_id"), nil + } + url := fmt.Sprintf("%s/users/%s/attestations/%s", cfg.BaseURL, username, attestation_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_attestations_by_idTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_users_username_attestations_attestation_id", + mcp.WithDescription("Delete attestations by ID"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("attestation_id", mcp.Required(), mcp.Description("Attestation ID")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_attestations_by_idHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_attestations_by_subject_digest.go b/MCP/tools/users/users_delete_attestations_by_subject_digest.go new file mode 100644 index 0000000..8f4af9c --- /dev/null +++ b/MCP/tools/users/users_delete_attestations_by_subject_digest.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_attestations_by_subject_digestHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + subject_digestVal, ok := args["subject_digest"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: subject_digest"), nil + } + subject_digest, ok := subject_digestVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: subject_digest"), nil + } + url := fmt.Sprintf("%s/users/%s/attestations/digest/%s", cfg.BaseURL, username, subject_digest) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_attestations_by_subject_digestTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_users_username_attestations_digest_subject_digest", + mcp.WithDescription("Delete attestations by subject digest"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("subject_digest", mcp.Required(), mcp.Description("Subject Digest")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_attestations_by_subject_digestHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_email_for_authenticated_user.go b/MCP/tools/users/users_delete_email_for_authenticated_user.go new file mode 100644 index 0000000..5312adf --- /dev/null +++ b/MCP/tools/users/users_delete_email_for_authenticated_user.go @@ -0,0 +1,86 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_email_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/emails", cfg.BaseURL) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_email_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_emails", + mcp.WithDescription("Delete an email address for the authenticated user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_email_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_gpg_key_for_authenticated_user.go b/MCP/tools/users/users_delete_gpg_key_for_authenticated_user.go new file mode 100644 index 0000000..6a8fdea --- /dev/null +++ b/MCP/tools/users/users_delete_gpg_key_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_gpg_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gpg_key_idVal, ok := args["gpg_key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gpg_key_id"), nil + } + gpg_key_id, ok := gpg_key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gpg_key_id"), nil + } + url := fmt.Sprintf("%s/user/gpg_keys/%s", cfg.BaseURL, gpg_key_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_gpg_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_gpg_keys_gpg_key_id", + mcp.WithDescription("Delete a GPG key for the authenticated user"), + mcp.WithNumber("gpg_key_id", mcp.Required(), mcp.Description("The unique identifier of the GPG key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_gpg_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_public_ssh_key_for_authenticated_user.go b/MCP/tools/users/users_delete_public_ssh_key_for_authenticated_user.go new file mode 100644 index 0000000..f572aa1 --- /dev/null +++ b/MCP/tools/users/users_delete_public_ssh_key_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_public_ssh_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + key_idVal, ok := args["key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: key_id"), nil + } + key_id, ok := key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: key_id"), nil + } + url := fmt.Sprintf("%s/user/keys/%s", cfg.BaseURL, key_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_public_ssh_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_keys_key_id", + mcp.WithDescription("Delete a public SSH key for the authenticated user"), + mcp.WithNumber("key_id", mcp.Required(), mcp.Description("The unique identifier of the key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_public_ssh_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_social_account_for_authenticated_user.go b/MCP/tools/users/users_delete_social_account_for_authenticated_user.go new file mode 100644 index 0000000..2e30641 --- /dev/null +++ b/MCP/tools/users/users_delete_social_account_for_authenticated_user.go @@ -0,0 +1,87 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_social_account_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/social_accounts", cfg.BaseURL) + req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_social_account_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_social_accounts", + mcp.WithDescription("Delete social accounts for the authenticated user"), + mcp.WithArray("account_urls", mcp.Required(), mcp.Description("Input parameter: Full URLs for the social media profiles to delete.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_social_account_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_delete_ssh_signing_key_for_authenticated_user.go b/MCP/tools/users/users_delete_ssh_signing_key_for_authenticated_user.go new file mode 100644 index 0000000..96d8c2d --- /dev/null +++ b/MCP/tools/users/users_delete_ssh_signing_key_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_delete_ssh_signing_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ssh_signing_key_idVal, ok := args["ssh_signing_key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ssh_signing_key_id"), nil + } + ssh_signing_key_id, ok := ssh_signing_key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ssh_signing_key_id"), nil + } + url := fmt.Sprintf("%s/user/ssh_signing_keys/%s", cfg.BaseURL, ssh_signing_key_id) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_delete_ssh_signing_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_ssh_signing_keys_ssh_signing_key_id", + mcp.WithDescription("Delete an SSH signing key for the authenticated user"), + mcp.WithNumber("ssh_signing_key_id", mcp.Required(), mcp.Description("The unique identifier of the SSH signing key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_delete_ssh_signing_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_follow.go b/MCP/tools/users/users_follow.go new file mode 100644 index 0000000..5492ff4 --- /dev/null +++ b/MCP/tools/users/users_follow.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_followHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/user/following/%s", cfg.BaseURL, username) + req, err := http.NewRequest("PUT", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_followTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("put_user_following_username", + mcp.WithDescription("Follow a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_followHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_authenticated.go b/MCP/tools/users/users_get_authenticated.go new file mode 100644 index 0000000..6dec91c --- /dev/null +++ b/MCP/tools/users/users_get_authenticated.go @@ -0,0 +1,64 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_authenticatedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + url := fmt.Sprintf("%s/user", cfg.BaseURL) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_authenticatedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user", + mcp.WithDescription("Get the authenticated user"), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_authenticatedHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_by_id.go b/MCP/tools/users/users_get_by_id.go new file mode 100644 index 0000000..6b21d75 --- /dev/null +++ b/MCP/tools/users/users_get_by_id.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_by_idHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + account_idVal, ok := args["account_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: account_id"), nil + } + account_id, ok := account_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: account_id"), nil + } + url := fmt.Sprintf("%s/user/%s", cfg.BaseURL, account_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_by_idTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_account_id", + mcp.WithDescription("Get a user using their ID"), + mcp.WithNumber("account_id", mcp.Required(), mcp.Description("account_id parameter")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_by_idHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_by_username.go b/MCP/tools/users/users_get_by_username.go new file mode 100644 index 0000000..7d7cedb --- /dev/null +++ b/MCP/tools/users/users_get_by_username.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_by_usernameHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/users/%s", cfg.BaseURL, username) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_by_usernameTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username", + mcp.WithDescription("Get a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_by_usernameHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_context_for_user.go b/MCP/tools/users/users_get_context_for_user.go new file mode 100644 index 0000000..8fe7a6e --- /dev/null +++ b/MCP/tools/users/users_get_context_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_context_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["subject_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("subject_type=%v", val)) + } + if val, ok := args["subject_id"]; ok { + queryParams = append(queryParams, fmt.Sprintf("subject_id=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/hovercard%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Hovercard + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_context_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_hovercard", + mcp.WithDescription("Get contextual information for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("subject_type", mcp.Description("Identifies which additional information you'd like to receive about the person's hovercard. Can be `organization`, `repository`, `issue`, `pull_request`. **Required** when using `subject_id`.")), + mcp.WithString("subject_id", mcp.Description("Uses the ID for the `subject_type` you specified. **Required** when using `subject_type`.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_context_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_gpg_key_for_authenticated_user.go b/MCP/tools/users/users_get_gpg_key_for_authenticated_user.go new file mode 100644 index 0000000..1400d8b --- /dev/null +++ b/MCP/tools/users/users_get_gpg_key_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_gpg_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + gpg_key_idVal, ok := args["gpg_key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: gpg_key_id"), nil + } + gpg_key_id, ok := gpg_key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: gpg_key_id"), nil + } + url := fmt.Sprintf("%s/user/gpg_keys/%s", cfg.BaseURL, gpg_key_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_gpg_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_gpg_keys_gpg_key_id", + mcp.WithDescription("Get a GPG key for the authenticated user"), + mcp.WithNumber("gpg_key_id", mcp.Required(), mcp.Description("The unique identifier of the GPG key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_gpg_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_public_ssh_key_for_authenticated_user.go b/MCP/tools/users/users_get_public_ssh_key_for_authenticated_user.go new file mode 100644 index 0000000..2b50f64 --- /dev/null +++ b/MCP/tools/users/users_get_public_ssh_key_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_public_ssh_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + key_idVal, ok := args["key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: key_id"), nil + } + key_id, ok := key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: key_id"), nil + } + url := fmt.Sprintf("%s/user/keys/%s", cfg.BaseURL, key_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.Key + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_public_ssh_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_keys_key_id", + mcp.WithDescription("Get a public SSH key for the authenticated user"), + mcp.WithNumber("key_id", mcp.Required(), mcp.Description("The unique identifier of the key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_public_ssh_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_get_ssh_signing_key_for_authenticated_user.go b/MCP/tools/users/users_get_ssh_signing_key_for_authenticated_user.go new file mode 100644 index 0000000..9056f04 --- /dev/null +++ b/MCP/tools/users/users_get_ssh_signing_key_for_authenticated_user.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_get_ssh_signing_key_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + ssh_signing_key_idVal, ok := args["ssh_signing_key_id"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: ssh_signing_key_id"), nil + } + ssh_signing_key_id, ok := ssh_signing_key_idVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: ssh_signing_key_id"), nil + } + url := fmt.Sprintf("%s/user/ssh_signing_keys/%s", cfg.BaseURL, ssh_signing_key_id) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_get_ssh_signing_key_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_ssh_signing_keys_ssh_signing_key_id", + mcp.WithDescription("Get an SSH signing key for the authenticated user"), + mcp.WithNumber("ssh_signing_key_id", mcp.Required(), mcp.Description("The unique identifier of the SSH signing key.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_get_ssh_signing_key_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list.go b/MCP/tools/users/users_list.go new file mode 100644 index 0000000..6329a44 --- /dev/null +++ b/MCP/tools/users/users_list.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_listHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["since"]; ok { + queryParams = append(queryParams, fmt.Sprintf("since=%v", val)) + } + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_listTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users", + mcp.WithDescription("List users"), + mcp.WithNumber("since", mcp.Description("A user ID. Only return users with an ID greater than this ID.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_listHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_attestations.go b/MCP/tools/users/users_list_attestations.go new file mode 100644 index 0000000..6abac84 --- /dev/null +++ b/MCP/tools/users/users_list_attestations.go @@ -0,0 +1,108 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_attestationsHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + subject_digestVal, ok := args["subject_digest"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: subject_digest"), nil + } + subject_digest, ok := subject_digestVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: subject_digest"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + if val, ok := args["predicate_type"]; ok { + queryParams = append(queryParams, fmt.Sprintf("predicate_type=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/attestations/%s%s", cfg.BaseURL, username, subject_digest, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_attestationsTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_attestations_subject_digest", + mcp.WithDescription("List attestations"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("subject_digest", mcp.Required(), mcp.Description("Subject Digest")), + mcp.WithString("predicate_type", mcp.Description("Optional filter for fetching attestations with a given predicate type.\nThis option accepts `provenance`, `sbom`, or freeform text for custom predicate types.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_attestationsHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_attestations_bulk.go b/MCP/tools/users/users_list_attestations_bulk.go new file mode 100644 index 0000000..421f3b4 --- /dev/null +++ b/MCP/tools/users/users_list_attestations_bulk.go @@ -0,0 +1,115 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_attestations_bulkHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["before"]; ok { + queryParams = append(queryParams, fmt.Sprintf("before=%v", val)) + } + if val, ok := args["after"]; ok { + queryParams = append(queryParams, fmt.Sprintf("after=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/users/%s/attestations/bulk-list%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("POST", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_attestations_bulkTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("post_users_username_attestations_bulk-list", + mcp.WithDescription("List attestations by bulk subject digests"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("before", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results before this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("after", mcp.Description("A cursor, as given in the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers). If specified, the query only searches for results after this cursor. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithString("predicate_type", mcp.Description("Input parameter: Optional filter for fetching attestations with a given predicate type.\nThis option accepts `provenance`, `sbom`, or freeform text for custom predicate types.")), + mcp.WithArray("subject_digests", mcp.Required(), mcp.Description("Input parameter: List of subject digests to fetch attestations for.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_attestations_bulkHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_blocked_by_authenticated_user.go b/MCP/tools/users/users_list_blocked_by_authenticated_user.go new file mode 100644 index 0000000..9bd2276 --- /dev/null +++ b/MCP/tools/users/users_list_blocked_by_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_blocked_by_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/blocks%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_blocked_by_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_blocks", + mcp.WithDescription("List users blocked by the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_blocked_by_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_emails_for_authenticated_user.go b/MCP/tools/users/users_list_emails_for_authenticated_user.go new file mode 100644 index 0000000..dd0728e --- /dev/null +++ b/MCP/tools/users/users_list_emails_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_emails_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/emails%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Email + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_emails_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_emails", + mcp.WithDescription("List email addresses for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_emails_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_followed_by_authenticated_user.go b/MCP/tools/users/users_list_followed_by_authenticated_user.go new file mode 100644 index 0000000..a46bfd8 --- /dev/null +++ b/MCP/tools/users/users_list_followed_by_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_followed_by_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/following%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_followed_by_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_following", + mcp.WithDescription("List the people the authenticated user follows"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_followed_by_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_followers_for_authenticated_user.go b/MCP/tools/users/users_list_followers_for_authenticated_user.go new file mode 100644 index 0000000..50b9c98 --- /dev/null +++ b/MCP/tools/users/users_list_followers_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_followers_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/followers%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_followers_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_followers", + mcp.WithDescription("List followers of the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_followers_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_followers_for_user.go b/MCP/tools/users/users_list_followers_for_user.go new file mode 100644 index 0000000..d62153f --- /dev/null +++ b/MCP/tools/users/users_list_followers_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_followers_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/followers%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_followers_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_followers", + mcp.WithDescription("List followers of a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_followers_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_following_for_user.go b/MCP/tools/users/users_list_following_for_user.go new file mode 100644 index 0000000..76258fe --- /dev/null +++ b/MCP/tools/users/users_list_following_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_following_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/following%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_following_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_following", + mcp.WithDescription("List the people a user follows"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_following_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_gpg_keys_for_authenticated_user.go b/MCP/tools/users/users_list_gpg_keys_for_authenticated_user.go new file mode 100644 index 0000000..2e5a1a8 --- /dev/null +++ b/MCP/tools/users/users_list_gpg_keys_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_gpg_keys_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/gpg_keys%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_gpg_keys_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_gpg_keys", + mcp.WithDescription("List GPG keys for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_gpg_keys_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_gpg_keys_for_user.go b/MCP/tools/users/users_list_gpg_keys_for_user.go new file mode 100644 index 0000000..b3c7d81 --- /dev/null +++ b/MCP/tools/users/users_list_gpg_keys_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_gpg_keys_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/gpg_keys%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_gpg_keys_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_gpg_keys", + mcp.WithDescription("List GPG keys for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_gpg_keys_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_public_emails_for_authenticated_user.go b/MCP/tools/users/users_list_public_emails_for_authenticated_user.go new file mode 100644 index 0000000..e9295b0 --- /dev/null +++ b/MCP/tools/users/users_list_public_emails_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_public_emails_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/public_emails%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Email + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_public_emails_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_public_emails", + mcp.WithDescription("List public email addresses for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_public_emails_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_public_keys_for_user.go b/MCP/tools/users/users_list_public_keys_for_user.go new file mode 100644 index 0000000..a770bb7 --- /dev/null +++ b/MCP/tools/users/users_list_public_keys_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_public_keys_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/keys%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_public_keys_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_keys", + mcp.WithDescription("List public keys for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_public_keys_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_public_ssh_keys_for_authenticated_user.go b/MCP/tools/users/users_list_public_ssh_keys_for_authenticated_user.go new file mode 100644 index 0000000..209168f --- /dev/null +++ b/MCP/tools/users/users_list_public_ssh_keys_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_public_ssh_keys_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/keys%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Key + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_public_ssh_keys_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_keys", + mcp.WithDescription("List public SSH keys for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_public_ssh_keys_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_social_accounts_for_authenticated_user.go b/MCP/tools/users/users_list_social_accounts_for_authenticated_user.go new file mode 100644 index 0000000..14937ea --- /dev/null +++ b/MCP/tools/users/users_list_social_accounts_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_social_accounts_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/social_accounts%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_social_accounts_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_social_accounts", + mcp.WithDescription("List social accounts for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_social_accounts_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_social_accounts_for_user.go b/MCP/tools/users/users_list_social_accounts_for_user.go new file mode 100644 index 0000000..cbd7a3d --- /dev/null +++ b/MCP/tools/users/users_list_social_accounts_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_social_accounts_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/social_accounts%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_social_accounts_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_social_accounts", + mcp.WithDescription("List social accounts for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_social_accounts_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_ssh_signing_keys_for_authenticated_user.go b/MCP/tools/users/users_list_ssh_signing_keys_for_authenticated_user.go new file mode 100644 index 0000000..0907785 --- /dev/null +++ b/MCP/tools/users/users_list_ssh_signing_keys_for_authenticated_user.go @@ -0,0 +1,82 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_ssh_signing_keys_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/user/ssh_signing_keys%s", cfg.BaseURL, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_ssh_signing_keys_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_user_ssh_signing_keys", + mcp.WithDescription("List SSH signing keys for the authenticated user"), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_ssh_signing_keys_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_list_ssh_signing_keys_for_user.go b/MCP/tools/users/users_list_ssh_signing_keys_for_user.go new file mode 100644 index 0000000..fbe00eb --- /dev/null +++ b/MCP/tools/users/users_list_ssh_signing_keys_for_user.go @@ -0,0 +1,91 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_list_ssh_signing_keys_for_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + queryParams := make([]string, 0) + if val, ok := args["per_page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("per_page=%v", val)) + } + if val, ok := args["page"]; ok { + queryParams = append(queryParams, fmt.Sprintf("page=%v", val)) + } + queryString := "" + if len(queryParams) > 0 { + queryString = "?" + strings.Join(queryParams, "&") + } + url := fmt.Sprintf("%s/users/%s/ssh_signing_keys%s", cfg.BaseURL, username, queryString) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_list_ssh_signing_keys_for_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("get_users_username_ssh_signing_keys", + mcp.WithDescription("List SSH signing keys for a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + mcp.WithNumber("per_page", mcp.Description("The number of results per page (max 100). For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + mcp.WithNumber("page", mcp.Description("The page number of the results to fetch. For more information, see \"[Using pagination in the REST API](https://docs.github.com/rest/using-the-rest-api/using-pagination-in-the-rest-api).\"")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_list_ssh_signing_keys_for_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_set_primary_email_visibility_for_authenticated_user.go b/MCP/tools/users/users_set_primary_email_visibility_for_authenticated_user.go new file mode 100644 index 0000000..46f280e --- /dev/null +++ b/MCP/tools/users/users_set_primary_email_visibility_for_authenticated_user.go @@ -0,0 +1,87 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_set_primary_email_visibility_for_authenticated_userHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user/email/visibility", cfg.BaseURL) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result []Email + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_set_primary_email_visibility_for_authenticated_userTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_user_email_visibility", + mcp.WithDescription("Set primary email visibility for the authenticated user"), + mcp.WithString("visibility", mcp.Required(), mcp.Description("Input parameter: Denotes whether an email is publicly visible.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_set_primary_email_visibility_for_authenticated_userHandler(cfg), + } +} diff --git a/MCP/tools/users/users_unblock.go b/MCP/tools/users/users_unblock.go new file mode 100644 index 0000000..47bb570 --- /dev/null +++ b/MCP/tools/users/users_unblock.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_unblockHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/user/blocks/%s", cfg.BaseURL, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_unblockTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_blocks_username", + mcp.WithDescription("Unblock a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_unblockHandler(cfg), + } +} diff --git a/MCP/tools/users/users_unfollow.go b/MCP/tools/users/users_unfollow.go new file mode 100644 index 0000000..aadac32 --- /dev/null +++ b/MCP/tools/users/users_unfollow.go @@ -0,0 +1,77 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_unfollowHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + usernameVal, ok := args["username"] + if !ok { + return mcp.NewToolResultError("Missing required path parameter: username"), nil + } + username, ok := usernameVal.(string) + if !ok { + return mcp.NewToolResultError("Invalid path parameter: username"), nil + } + url := fmt.Sprintf("%s/user/following/%s", cfg.BaseURL, username) + req, err := http.NewRequest("DELETE", url, nil) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result map[string]interface{} + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_unfollowTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("delete_user_following_username", + mcp.WithDescription("Unfollow a user"), + mcp.WithString("username", mcp.Required(), mcp.Description("The handle for the GitHub user account.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_unfollowHandler(cfg), + } +} diff --git a/MCP/tools/users/users_update_authenticated.go b/MCP/tools/users/users_update_authenticated.go new file mode 100644 index 0000000..0b46ee9 --- /dev/null +++ b/MCP/tools/users/users_update_authenticated.go @@ -0,0 +1,94 @@ +package tools + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "bytes" + + "github.com/github-v3-rest-api/mcp-server/config" + "github.com/github-v3-rest-api/mcp-server/models" + "github.com/mark3labs/mcp-go/mcp" +) + +func Users_update_authenticatedHandler(cfg *config.APIConfig) func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + args, ok := request.Params.Arguments.(map[string]any) + if !ok { + return mcp.NewToolResultError("Invalid arguments object"), nil + } + // Create properly typed request body using the generated schema + var requestBody map[string]interface{} + + // Optimized: Single marshal/unmarshal with JSON tags handling field mapping + if argsJSON, err := json.Marshal(args); err == nil { + if err := json.Unmarshal(argsJSON, &requestBody); err != nil { + return mcp.NewToolResultError(fmt.Sprintf("Failed to convert arguments to request type: %v", err)), nil + } + } else { + return mcp.NewToolResultError(fmt.Sprintf("Failed to marshal arguments: %v", err)), nil + } + + bodyBytes, err := json.Marshal(requestBody) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to encode request body", err), nil + } + url := fmt.Sprintf("%s/user", cfg.BaseURL) + req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(bodyBytes)) + req.Header.Set("Content-Type", "application/json") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to create request", err), nil + } + // No authentication required for this endpoint + req.Header.Set("Accept", "application/json") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return mcp.NewToolResultErrorFromErr("Request failed", err), nil + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to read response body", err), nil + } + + if resp.StatusCode >= 400 { + return mcp.NewToolResultError(fmt.Sprintf("API error: %s", body)), nil + } + // Use properly typed response + var result models.GeneratedType + if err := json.Unmarshal(body, &result); err != nil { + // Fallback to raw text if unmarshaling fails + return mcp.NewToolResultText(string(body)), nil + } + + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return mcp.NewToolResultErrorFromErr("Failed to format JSON", err), nil + } + + return mcp.NewToolResultText(string(prettyJSON)), nil + } +} + +func CreateUsers_update_authenticatedTool(cfg *config.APIConfig) models.Tool { + tool := mcp.NewTool("patch_user", + mcp.WithDescription("Update the authenticated user"), + mcp.WithString("email", mcp.Description("Input parameter: The publicly visible email address of the user.")), + mcp.WithBoolean("hireable", mcp.Description("Input parameter: The new hiring availability of the user.")), + mcp.WithString("location", mcp.Description("Input parameter: The new location of the user.")), + mcp.WithString("name", mcp.Description("Input parameter: The new name of the user.")), + mcp.WithString("twitter_username", mcp.Description("Input parameter: The new Twitter username of the user.")), + mcp.WithString("bio", mcp.Description("Input parameter: The new short biography of the user.")), + mcp.WithString("blog", mcp.Description("Input parameter: The new blog URL of the user.")), + mcp.WithString("company", mcp.Description("Input parameter: The new company of the user.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_update_authenticatedHandler(cfg), + } +} From 11376027975837d98226128ed966372c6d58405d Mon Sep 17 00:00:00 2001 From: Madhavi Pasumarthi Date: Tue, 23 Sep 2025 16:05:11 -0400 Subject: [PATCH 2/2] Create devcontainer.json --- .devcontainer/devcontainer.json | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..a4924a0 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,40 @@ +{ + "name": "CodeGlide MCP Server", + "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye", + "features": { + "ghcr.io/devcontainers/features/docker-in-docker:2": {}, + "ghcr.io/devcontainers/features/git:1": {} + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.vscode-typescript-next", + "bradlc.vscode-tailwindcss", + "esbenp.prettier-vscode", + "ms-vscode.vscode-json" + ], + "settings": { + "terminal.integrated.defaultProfile.linux": "bash", + "terminal.integrated.profiles.linux": { + "bash": { + "path": "/bin/bash" + } + } + } + } + }, + "postCreateCommand": "bash .devcontainer/setup.sh", + "postStartCommand": "bash .devcontainer/start-mcp.sh", + "forwardPorts": [3000, 8080], + "portsAttributes": { + "3000": { + "label": "MCP Server", + "onAutoForward": "notify" + }, + "8080": { + "label": "API Server", + "onAutoForward": "notify" + } + }, + "remoteUser": "node" +}