From 09be0de94fdfed788665ee8ac8a494e30c18bea7 Mon Sep 17 00:00:00 2001 From: "codeglide[bot]" <223743026+codeglide[bot]@users.noreply.github.com> Date: Mon, 11 Aug 2025 00:03:42 +0000 Subject: [PATCH] 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..9769846 --- /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) +} + +// Webhooksproject represents the Webhooksproject schema from the OpenAPI specification +type Webhooksproject struct { + Body string `json:"body"` // Body of the project + Updated_at string `json:"updated_at"` + Columns_url string `json:"columns_url"` + Creator map[string]interface{} `json:"creator"` + Number int `json:"number"` + State string `json:"state"` // State of the project; either 'open' or 'closed' + Url string `json:"url"` + Created_at string `json:"created_at"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Name string `json:"name"` // Name of the project + Node_id string `json:"node_id"` + Owner_url string `json:"owner_url"` +} + +// 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 { + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// 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"` + 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)." +} + +// 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. + 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"` + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Color string `json:"color"` + DefaultField bool `json:"default"` + Description string `json:"description"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Score float64 `json:"score"` + Url string `json:"url"` + Name string `json:"name"` +} + +// Team represents the Team schema from the OpenAPI specification +type Team struct { + Parent GeneratedType `json:"parent"` // Groups of organization members that gives permissions on specified repositories. + Permission string `json:"permission"` + Repositories_url string `json:"repositories_url"` + Name string `json:"name"` + Privacy string `json:"privacy,omitempty"` + Slug string `json:"slug"` + Url string `json:"url"` + Html_url string `json:"html_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Description string `json:"description"` + Members_url string `json:"members_url"` + Notification_setting string `json:"notification_setting,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Forks_url string `json:"forks_url"` + Has_pages bool `json:"has_pages,omitempty"` + Forks_count int `json:"forks_count,omitempty"` + Labels_url string `json:"labels_url"` + Events_url string `json:"events_url"` + Issue_events_url string `json:"issue_events_url"` + Issues_url string `json:"issues_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Has_downloads bool `json:"has_downloads,omitempty"` + Pushed_at string `json:"pushed_at,omitempty"` + Stargazers_url string `json:"stargazers_url"` + Role_name string `json:"role_name,omitempty"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Open_issues int `json:"open_issues,omitempty"` + Keys_url string `json:"keys_url"` + Releases_url string `json:"releases_url"` + Clone_url string `json:"clone_url,omitempty"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Description string `json:"description"` + 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. + 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. + Git_refs_url string `json:"git_refs_url"` + Ssh_url string `json:"ssh_url,omitempty"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Code_of_conduct GeneratedType `json:"code_of_conduct,omitempty"` // Code Of Conduct + Downloads_url string `json:"downloads_url"` + Contributors_url string `json:"contributors_url"` + Stargazers_count int `json:"stargazers_count,omitempty"` + Network_count int `json:"network_count,omitempty"` + Assignees_url string `json:"assignees_url"` + Has_issues bool `json:"has_issues,omitempty"` + Trees_url string `json:"trees_url"` + Disabled bool `json:"disabled,omitempty"` + Fork bool `json:"fork"` + Has_wiki bool `json:"has_wiki,omitempty"` + Allow_forking bool `json:"allow_forking,omitempty"` + Issue_comment_url string `json:"issue_comment_url"` + Subscribers_url string `json:"subscribers_url"` + Compare_url string `json:"compare_url"` + Git_url string `json:"git_url,omitempty"` + Has_projects bool `json:"has_projects,omitempty"` + Archived bool `json:"archived,omitempty"` + Branches_url string `json:"branches_url"` + Contents_url string `json:"contents_url"` + Private bool `json:"private"` + Url string `json:"url"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Name string `json:"name"` + Homepage string `json:"homepage,omitempty"` + Statuses_url string `json:"statuses_url"` + Security_and_analysis GeneratedType `json:"security_and_analysis,omitempty"` + Languages_url string `json:"languages_url"` + Default_branch string `json:"default_branch,omitempty"` + Subscription_url string `json:"subscription_url"` + Tags_url string `json:"tags_url"` + Comments_url string `json:"comments_url"` + Deployments_url string `json:"deployments_url"` + Html_url string `json:"html_url"` + Git_commits_url string `json:"git_commits_url"` + Full_name string `json:"full_name"` + Merges_url string `json:"merges_url"` + Hooks_url string `json:"hooks_url"` + Is_template bool `json:"is_template,omitempty"` + Blobs_url string `json:"blobs_url"` + Notifications_url string `json:"notifications_url"` + Language string `json:"language,omitempty"` + Watchers int `json:"watchers,omitempty"` + License map[string]interface{} `json:"license,omitempty"` + Visibility string `json:"visibility,omitempty"` + Topics []string `json:"topics,omitempty"` + Commits_url string `json:"commits_url"` + Pulls_url string `json:"pulls_url"` + Mirror_url string `json:"mirror_url,omitempty"` + Collaborators_url string `json:"collaborators_url"` + Milestones_url string `json:"milestones_url"` + Git_tags_url string `json:"git_tags_url"` + Archive_url string `json:"archive_url"` + Svn_url string `json:"svn_url,omitempty"` + Id int64 `json:"id"` + Watchers_count int `json:"watchers_count,omitempty"` + Open_issues_count int `json:"open_issues_count,omitempty"` + Has_discussions bool `json:"has_discussions,omitempty"` + Forks int `json:"forks,omitempty"` + Teams_url string `json:"teams_url"` + Updated_at string `json:"updated_at,omitempty"` + Node_id string `json:"node_id"` + Subscribers_count int `json:"subscribers_count,omitempty"` +} + +// Label represents the Label schema from the OpenAPI specification +type Label struct { + 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 + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Title string `json:"title"` + Url string `json:"url"` + Added_by string `json:"added_by,omitempty"` + 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"` + Last_used string `json:"last_used,omitempty"` +} + +// 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 { + Event string `json:"event"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Assigner GeneratedType `json:"assigner"` // A GitHub user. + Commit_id string `json:"commit_id"` + Id int `json:"id"` + 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. + Actor GeneratedType `json:"actor"` // A GitHub user. + Created_at string `json:"created_at"` + Url string `json:"url"` + Commit_url string `json:"commit_url"` +} + +// 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 { + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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"` +} + +// Commit represents the Commit schema from the OpenAPI specification +type Commit struct { + Sha string `json:"sha"` + Url string `json:"url"` + Author interface{} `json:"author"` + Node_id string `json:"node_id"` + Stats map[string]interface{} `json:"stats,omitempty"` + Comments_url string `json:"comments_url"` + Html_url string `json:"html_url"` + Commit map[string]interface{} `json:"commit"` + Committer interface{} `json:"committer"` + Files []GeneratedType `json:"files,omitempty"` + Parents []map[string]interface{} `json:"parents"` +} + +// 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Pull_request map[string]interface{} `json:"pull_request"` + 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. + Assignee Webhooksuser `json:"assignee"` + 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. +} + +// 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 { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` // The ID of the installation. + Node_id string `json:"node_id"` // The global node ID of the installation. +} + +// 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 { + Columns_url string `json:"columns_url"` + Updated_at string `json:"updated_at"` + Id int `json:"id"` + Number int `json:"number"` + Owner_url string `json:"owner_url"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Private bool `json:"private,omitempty"` // Whether the project is private or not. Only present when owner is an organization. + Url string `json:"url"` + Body string `json:"body"` + Permissions map[string]interface{} `json:"permissions"` + Html_url string `json:"html_url"` + State string `json:"state"` + Node_id string `json:"node_id"` + Name string `json:"name"` + Organization_permission string `json:"organization_permission,omitempty"` // The organization permission for this project. Only present when owner is an organization. + Created_at string `json:"created_at"` +} + +// 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Default_level string `json:"default_level,omitempty"` // The default repository access level for Dependabot updates. + Accessible_repositories []GeneratedType `json:"accessible_repositories,omitempty"` +} + +// 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 { + Ref_name map[string]interface{} `json:"ref_name,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"` // 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Number int `json:"number"` + Pull_request map[string]interface{} `json:"pull_request"` + Reason string `json:"reason"` + 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. + 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 { + Parameters map[string]interface{} `json:"parameters,omitempty"` + 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,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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int64 `json:"id"` + Node_id string `json:"node_id"` + Repos_url string `json:"repos_url"` + Following_url string `json:"following_url"` + Gravatar_id string `json:"gravatar_id"` + Html_url string `json:"html_url"` + Url string `json:"url"` + Site_admin bool `json:"site_admin"` + Organizations_url string `json:"organizations_url"` + TypeField string `json:"type"` + Received_events_url string `json:"received_events_url"` + Events_url string `json:"events_url"` + Email string `json:"email,omitempty"` + Avatar_url string `json:"avatar_url"` + Login string `json:"login"` + Starred_url string `json:"starred_url"` + Subscriptions_url string `json:"subscriptions_url"` + User_view_type string `json:"user_view_type,omitempty"` + Followers_url string `json:"followers_url"` + Name string `json:"name,omitempty"` + Starred_at string `json:"starred_at,omitempty"` + Gists_url string `json:"gists_url"` +} + +// 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 +} + +// Workflow represents the Workflow schema from the OpenAPI specification +type Workflow struct { + Url string `json:"url"` + Name string `json:"name"` + State string `json:"state"` + Deleted_at string `json:"deleted_at,omitempty"` + Path string `json:"path"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Badge_url string `json:"badge_url"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pattern_update_scans []GeneratedType `json:"pattern_update_scans,omitempty"` + 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"` +} + +// 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. + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Deleted_at string `json:"deleted_at"` + Description string `json:"description"` + Public bool `json:"public"` + Short_description string `json:"short_description"` + Closed_at string `json:"closed_at"` + Created_at string `json:"created_at"` + Deleted_by GeneratedType `json:"deleted_by"` // A GitHub user. + Id float64 `json:"id"` + Updated_at string `json:"updated_at"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Title string `json:"title"` + Node_id string `json:"node_id"` + Number int `json:"number"` + Owner GeneratedType `json:"owner"` // A GitHub user. +} + +// 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Url string `json:"url"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + State_reason string `json:"state_reason,omitempty"` + 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. + Commit_id string `json:"commit_id"` + Commit_url string `json:"commit_url"` + Event string `json:"event"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Body string `json:"body,omitempty"` + 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 { + 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. +} + +// Job represents the Job schema from the OpenAPI specification +type Job struct { + Created_at string `json:"created_at"` // The time that the job created, in ISO 8601 format. + 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.) + Started_at string `json:"started_at"` // The time that the job started, in ISO 8601 format. + Workflow_name string `json:"workflow_name"` // The name of the workflow. + Run_url string `json:"run_url"` + 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.) + Url string `json:"url"` + Completed_at string `json:"completed_at"` // The time that the job finished, in ISO 8601 format. + Name string `json:"name"` // The name of the job. + Check_run_url string `json:"check_run_url"` + Head_branch string `json:"head_branch"` // The name of the current branch. + Head_sha string `json:"head_sha"` // The SHA of the commit that is being run. + Labels []string `json:"labels"` // Labels for the workflow job. Specified by the "runs_on" attribute in the action's workflow file. + Run_id int `json:"run_id"` // The id of the associated workflow run. + 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. + Conclusion string `json:"conclusion"` // The outcome of the job. + 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"` + Html_url string `json:"html_url"` + 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.) + Status string `json:"status"` // The phase of the lifecycle that the job is currently in. + Id int `json:"id"` // The id of the job. +} + +// 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 { + 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. +} + +// Webhooksprojectcard represents the Webhooksprojectcard schema from the OpenAPI specification +type Webhooksprojectcard struct { + Project_url string `json:"project_url"` + After_id int `json:"after_id,omitempty"` + Column_id int `json:"column_id"` + Note string `json:"note"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Archived bool `json:"archived"` // Whether or not the card is archived + Column_url string `json:"column_url"` + Content_url string `json:"content_url,omitempty"` + Created_at string `json:"created_at"` + Creator map[string]interface{} `json:"creator"` + Id int `json:"id"` // The project card's ID + Node_id string `json:"node_id"` +} + +// Thread represents the Thread schema from the OpenAPI specification +type Thread struct { + Last_read_at string `json:"last_read_at"` + Reason string `json:"reason"` + Subscription_url string `json:"subscription_url"` + Unread bool `json:"unread"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Id string `json:"id"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Subject map[string]interface{} `json:"subject"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Deployment_status map[string]interface{} `json:"deployment_status"` // The [deployment status](https://docs.github.com/rest/deployments/statuses#list-deployment-statuses). + 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. + Deployment map[string]interface{} `json:"deployment"` // The [deployment](https://docs.github.com/rest/deployments/deployments#list-deployments). + 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. + Check_run map[string]interface{} `json:"check_run,omitempty"` + Workflow Webhooksworkflow `json:"workflow,omitempty"` + Workflow_run map[string]interface{} `json:"workflow_run,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Status string `json:"status"` +} + +// 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. + Repository GeneratedType `json:"repository,omitempty"` // A GitHub repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Location string `json:"location,omitempty"` + Members_can_change_repo_visibility bool `json:"members_can_change_repo_visibility,omitempty"` + Members_can_create_private_repositories bool `json:"members_can_create_private_repositories,omitempty"` + Two_factor_requirement_enabled bool `json:"two_factor_requirement_enabled,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. + Description string `json:"description"` + Archived_at string `json:"archived_at"` + Members_can_delete_issues bool `json:"members_can_delete_issues,omitempty"` + Members_can_invite_outside_collaborators bool `json:"members_can_invite_outside_collaborators,omitempty"` + Followers int `json:"followers"` + Created_at string `json:"created_at"` + Members_can_create_public_pages bool `json:"members_can_create_public_pages,omitempty"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Email string `json:"email,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. + 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. + Node_id string `json:"node_id"` + Url string `json:"url"` + Total_private_repos int `json:"total_private_repos,omitempty"` + Login string `json:"login"` + Updated_at string `json:"updated_at"` + Members_can_create_public_repositories bool `json:"members_can_create_public_repositories,omitempty"` + Default_repository_permission string `json:"default_repository_permission,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. + Html_url string `json:"html_url"` + Public_members_url string `json:"public_members_url"` + Display_commenter_full_name_setting_enabled bool `json:"display_commenter_full_name_setting_enabled,omitempty"` + Members_can_create_private_pages bool `json:"members_can_create_private_pages,omitempty"` + Members_can_create_internal_repositories bool `json:"members_can_create_internal_repositories,omitempty"` + Id int `json:"id"` + Members_can_create_repositories bool `json:"members_can_create_repositories,omitempty"` + Billing_email string `json:"billing_email,omitempty"` + Blog string `json:"blog,omitempty"` + Company string `json:"company,omitempty"` + 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. + Disk_usage int `json:"disk_usage,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. + Twitter_username string `json:"twitter_username,omitempty"` + Default_repository_branch string `json:"default_repository_branch,omitempty"` // The default branch for repositories created in this organization. + Members_url string `json:"members_url"` + 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. + Owned_private_repos int `json:"owned_private_repos,omitempty"` + Name string `json:"name,omitempty"` + Avatar_url string `json:"avatar_url"` + 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. + Is_verified bool `json:"is_verified,omitempty"` + Members_can_create_teams bool `json:"members_can_create_teams,omitempty"` + Members_can_view_dependency_insights bool `json:"members_can_view_dependency_insights,omitempty"` + Members_can_fork_private_repositories bool `json:"members_can_fork_private_repositories,omitempty"` + Issues_url string `json:"issues_url"` + Plan map[string]interface{} `json:"plan,omitempty"` + Members_allowed_repository_creation_type string `json:"members_allowed_repository_creation_type,omitempty"` + Has_repository_projects bool `json:"has_repository_projects"` + Members_can_create_pages bool `json:"members_can_create_pages,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. + Events_url string `json:"events_url"` + TypeField string `json:"type"` + Public_gists int `json:"public_gists"` + Members_can_delete_repositories bool `json:"members_can_delete_repositories,omitempty"` + Has_organization_projects bool `json:"has_organization_projects"` + 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. + Following int `json:"following"` + Public_repos int `json:"public_repos"` + Hooks_url string `json:"hooks_url"` + Private_gists int `json:"private_gists,omitempty"` + Repos_url string `json:"repos_url"` + Readers_can_create_discussions bool `json:"readers_can_create_discussions,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Runner_label string `json:"runner_label,omitempty"` // The label of the runner to use for code scanning default setup when runner_type is 'labeled'. + Runner_type string `json:"runner_type,omitempty"` // Whether to use labeled runners or standard GitHub runners. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Owner GeneratedType `json:"owner"` // A GitHub user. + Name string `json:"name"` // Automatically generated name of this codespace. + Billable_owner GeneratedType `json:"billable_owner"` // A GitHub user. + State string `json:"state"` // State of this codespace. + Stop_url string `json:"stop_url"` // API URL to stop this codespace. + Id int64 `json:"id"` + Runtime_constraints map[string]interface{} `json:"runtime_constraints,omitempty"` + Idle_timeout_minutes int `json:"idle_timeout_minutes"` // The number of minutes of inactivity after which this codespace will be automatically stopped. + 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 + Url string `json:"url"` // API URL for this codespace. + Start_url string `json:"start_url"` // API URL to start this codespace. + Display_name string `json:"display_name,omitempty"` // Display name for this codespace. + Last_used_at string `json:"last_used_at"` // Last known time this codespace was started. + Repository GeneratedType `json:"repository"` // Full Repository + 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" + Machines_url string `json:"machines_url"` // API URL to access available alternate machine types for this codespace. + Git_status map[string]interface{} `json:"git_status"` // Details about the codespace's git repository. + Location string `json:"location"` // The initally assigned location of a new 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 + Machine GeneratedType `json:"machine"` // A description of the machine powering a codespace. + Prebuild bool `json:"prebuild"` // Whether the codespace was created from a prebuild. + Environment_id string `json:"environment_id"` // UUID identifying this codespace's environment. + 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. + 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). + Web_url string `json:"web_url"` // URL to access this codespace on the web. + Recent_folders []string `json:"recent_folders"` + Created_at string `json:"created_at"` + Pulls_url string `json:"pulls_url"` // API URL for the Pull Request associated with this codespace, if any. + Updated_at string `json:"updated_at"` + Publish_url string `json:"publish_url,omitempty"` // API URL to publish this codespace to a new repository. +} + +// 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 { + Owner []int `json:"owner"` + All []int `json:"all"` +} + +// Webhooksmilestone represents the Webhooksmilestone schema from the OpenAPI specification +type Webhooksmilestone struct { + Html_url string `json:"html_url"` + Url string `json:"url"` + Creator map[string]interface{} `json:"creator"` + Updated_at string `json:"updated_at"` + Id int `json:"id"` + Labels_url string `json:"labels_url"` + Node_id string `json:"node_id"` + Closed_at string `json:"closed_at"` + Description string `json:"description"` + Open_issues int `json:"open_issues"` + Created_at string `json:"created_at"` + Number int `json:"number"` // The number of the milestone. + State string `json:"state"` // The state of the milestone. + Closed_issues int `json:"closed_issues"` + Due_on string `json:"due_on"` + Title string `json:"title"` // The title of the milestone. +} + +// 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 { + 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"` + Check_suite map[string]interface{} `json:"check_suite"` // The [check_suite](https://docs.github.com/rest/checks/suites#get-a-check-suite). +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Source_type string `json:"source_type,omitempty"` // The source type of the property + Value_type string `json:"value_type"` // The type of the value for 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. + Values_editable_by string `json:"values_editable_by,omitempty"` // Who can edit the values of the property + Property_name string `json:"property_name"` // The name of the property + Description string `json:"description,omitempty"` // Short description 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 + Required bool `json:"required,omitempty"` // Whether the property is required. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description,omitempty"` + Id string `json:"id"` + Name string `json:"name"` + Color string `json:"color,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 { + Run_url string `json:"run_url,omitempty"` // URL of the corresponding run. + Run_id int `json:"run_id,omitempty"` // ID of the corresponding run. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender map[string]interface{} `json:"sender"` + Team Webhooksteam `json:"team"` // Groups of organization members that gives permissions on specified repositories. + 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. + Scope string `json:"scope"` // The scope of the membership. Currently, can only be `team`. + Action string `json:"action"` + Member Webhooksuser `json:"member"` + 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. +} + +// 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 { + 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. +} + +// Webhooksrelease1 represents the Webhooksrelease1 schema from the OpenAPI specification +type Webhooksrelease1 struct { + Reactions map[string]interface{} `json:"reactions,omitempty"` + Body string `json:"body"` + Discussion_url string `json:"discussion_url,omitempty"` + Node_id string `json:"node_id"` + Assets_url string `json:"assets_url"` + Prerelease bool `json:"prerelease"` // Whether the release is identified as a prerelease or a full release. + Target_commitish string `json:"target_commitish"` // Specifies the commitish value that determines where the Git tag is created from. + Published_at string `json:"published_at"` + Url string `json:"url"` + Tarball_url string `json:"tarball_url"` + Created_at string `json:"created_at"` + Draft bool `json:"draft"` // Whether the release is a draft or published + Name string `json:"name"` + Zipball_url string `json:"zipball_url"` + Id int `json:"id"` + Author map[string]interface{} `json:"author"` + Tag_name string `json:"tag_name"` // The name of the tag. + Assets []map[string]interface{} `json:"assets"` + Upload_url string `json:"upload_url"` + Html_url string `json:"html_url"` +} + +// 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"` +} + +// Webhooksdeploykey represents the Webhooksdeploykey schema from the OpenAPI specification +type Webhooksdeploykey struct { + Added_by string `json:"added_by,omitempty"` + Last_used string `json:"last_used,omitempty"` + Verified bool `json:"verified"` + Enabled bool `json:"enabled,omitempty"` + Id int `json:"id"` + Read_only bool `json:"read_only"` + Created_at string `json:"created_at"` + Title string `json:"title"` + Url string `json:"url"` + Key string `json:"key"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Id int64 `json:"id"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Updated_at string `json:"updated_at"` + After string `json:"after"` + Head_branch string `json:"head_branch"` + Head_commit GeneratedType `json:"head_commit"` // A commit. + 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. + Before string `json:"before"` + Conclusion string `json:"conclusion"` + 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_runs_url string `json:"check_runs_url"` + Rerequestable bool `json:"rerequestable,omitempty"` + Latest_check_runs_count int `json:"latest_check_runs_count"` + Runs_rerequestable bool `json:"runs_rerequestable,omitempty"` + Url string `json:"url"` + Pull_requests []GeneratedType `json:"pull_requests"` + Node_id string `json:"node_id"` + Head_sha string `json:"head_sha"` // The SHA of the head commit that is being checked. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Cvss map[string]interface{} `json:"cvss"` // Details for the advisory pertaining to the Common Vulnerability Scoring System. + Cwes []map[string]interface{} `json:"cwes"` // Details for the advisory pertaining to Common Weakness Enumeration. + Published_at string `json:"published_at"` // The time that the advisory was published in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Summary string `json:"summary"` // A short, plain text summary of the advisory. + References []map[string]interface{} `json:"references"` // Links to additional advisory information. + Severity string `json:"severity"` // The severity of the advisory. + Updated_at string `json:"updated_at"` // The time that the advisory was last modified in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Description string `json:"description"` // A long-form Markdown-supported description of the advisory. + Withdrawn_at string `json:"withdrawn_at"` // The time that the advisory was withdrawn in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + Identifiers []map[string]interface{} `json:"identifiers"` // Values that identify this advisory among security information sources. + Vulnerabilities []GeneratedType `json:"vulnerabilities"` // Vulnerable version range information for the advisory. + Ghsa_id string `json:"ghsa_id"` // The unique GitHub Security Advisory ID assigned to the advisory. + Cve_id string `json:"cve_id"` // The unique CVE ID assigned to the advisory. + Epss GeneratedType `json:"epss,omitempty"` // The EPSS scores as calculated by the [Exploit Prediction Scoring System](https://www.first.org/epss). +} + +// 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 { + 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. + Token_type string `json:"token_type,omitempty"` // The token type this bypass is for. +} + +// 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 { + 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 { + 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 { + 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. + 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 { + Permission string `json:"permission"` + User GeneratedType `json:"user"` // A GitHub user. +} + +// 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"` +} + +// Runner represents the Runner schema from the OpenAPI specification +type Runner struct { + 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. + 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"` +} + +// Webhookssecurityadvisory represents the Webhookssecurityadvisory schema from the OpenAPI specification +type Webhookssecurityadvisory struct { + Published_at string `json:"published_at"` + Severity string `json:"severity"` + Summary string `json:"summary"` + Description string `json:"description"` + Updated_at string `json:"updated_at"` + Vulnerabilities []map[string]interface{} `json:"vulnerabilities"` + Cvss map[string]interface{} `json:"cvss"` + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + References []map[string]interface{} `json:"references"` + Withdrawn_at string `json:"withdrawn_at"` + Cwes []map[string]interface{} `json:"cwes"` + Ghsa_id string `json:"ghsa_id"` + Identifiers []map[string]interface{} `json:"identifiers"` +} + +// Webhookslabel represents the Webhookslabel schema from the OpenAPI specification +type Webhookslabel struct { + DefaultField bool `json:"default"` + 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 +} + +// 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 { + Status string `json:"status,omitempty"` + Url string `json:"url,omitempty"` + Documentation_url string `json:"documentation_url,omitempty"` + Message string `json:"message,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Site_admin bool `json:"site_admin"` + User_view_type string `json:"user_view_type,omitempty"` + Subscriptions_url string `json:"subscriptions_url"` + Hireable bool `json:"hireable,omitempty"` + Gists_url string `json:"gists_url"` + Login string `json:"login"` + Public_gists int `json:"public_gists,omitempty"` + Followers_url string `json:"followers_url"` + Avatar_url string `json:"avatar_url"` + Events_url string `json:"events_url"` + Starred_url string `json:"starred_url"` + Bio string `json:"bio,omitempty"` + Received_events_url string `json:"received_events_url"` + Gravatar_id string `json:"gravatar_id"` + Repos_url string `json:"repos_url"` + Suspended_at string `json:"suspended_at,omitempty"` + Updated_at string `json:"updated_at,omitempty"` + Email string `json:"email,omitempty"` + TypeField string `json:"type"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Score float64 `json:"score"` + Url string `json:"url"` + Followers int `json:"followers,omitempty"` + Blog string `json:"blog,omitempty"` + Following int `json:"following,omitempty"` + Company string `json:"company,omitempty"` + Created_at string `json:"created_at,omitempty"` + Name string `json:"name,omitempty"` + Public_repos int `json:"public_repos,omitempty"` + Following_url string `json:"following_url"` + Html_url string `json:"html_url"` + Organizations_url string `json:"organizations_url"` + Node_id string `json:"node_id"` + Id int64 `json:"id"` + Location string `json:"location,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,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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + 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"` +} + +// 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_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 { + Repositories_removed []map[string]interface{} `json:"repositories_removed"` // An array of repository objects, which were removed from the installation. + 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. + 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,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"` + 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. +} + +// 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. + 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. +} + +// 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 { + 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)." + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Html_url string `json:"html_url"` +} + +// Webhooksteam represents the Webhooksteam schema from the OpenAPI specification +type Webhooksteam struct { + Privacy string `json:"privacy,omitempty"` + Slug string `json:"slug,omitempty"` + Name string `json:"name"` // Name of the team + Parent map[string]interface{} `json:"parent,omitempty"` + Permission string `json:"permission,omitempty"` // Permission that the team will have for its repositories + Repositories_url string `json:"repositories_url,omitempty"` + Url string `json:"url,omitempty"` // URL for the team + Html_url string `json:"html_url,omitempty"` + Notification_setting string `json:"notification_setting,omitempty"` + Deleted bool `json:"deleted,omitempty"` + Description string `json:"description,omitempty"` // Description of the team + Id int `json:"id"` // Unique identifier of the team + Members_url string `json:"members_url,omitempty"` + Node_id string `json:"node_id,omitempty"` +} + +// 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 map[string]interface{} `json:"alert"` // The security alert of the vulnerable dependency. +} + +// 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 { + Enabled bool `json:"enabled"` // Whether Dependabot security updates are enabled for the repository. + Paused bool `json:"paused"` // Whether Dependabot security updates are paused for the repository. +} + +// Key represents the Key schema from the OpenAPI specification +type Key struct { + Read_only bool `json:"read_only"` + Title string `json:"title"` + Url string `json:"url"` + Verified bool `json:"verified"` + Created_at string `json:"created_at"` + Id int64 `json:"id"` + Key string `json:"key"` +} + +// 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. + 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. +} + +// 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_item GeneratedType `json:"projects_v2_item"` // An item 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 { + 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 { + Commit_id string `json:"commit_id"` + Event string `json:"event"` + Label map[string]interface{} `json:"label"` + Node_id string `json:"node_id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Id int `json:"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"` + Url string `json:"url"` +} + +// 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 +} + +// 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)." + 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. + Created bool `json:"created"` // Whether this push created the `ref`. + Ref string `json:"ref"` // The full git ref that was pushed. Example: `refs/heads/main` or `refs/tags/v3.14.1`. + Before string `json:"before"` // The SHA of the most recent commit on `ref` before the push. + 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. + 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)." + Head_commit map[string]interface{} `json:"head_commit"` + Forced bool `json:"forced"` // Whether this push was a force push of the `ref`. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Deleted bool `json:"deleted"` // Whether this push deleted the `ref`. + Pusher map[string]interface{} `json:"pusher"` // Metaproperties for Git author/committer information. + 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. + After string `json:"after"` // The SHA of the most recent commit on `ref` after the push. + Repository map[string]interface{} `json:"repository"` // A git repository +} + +// 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 { + Thread_url string `json:"thread_url,omitempty"` + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` // The action that was performed. + Assignee Webhooksuser `json:"assignee,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 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. +} + +// Actor represents the Actor schema from the OpenAPI specification +type Actor struct { + Gravatar_id string `json:"gravatar_id"` + Id int `json:"id"` + Login string `json:"login"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` + Display_login string `json:"display_login,omitempty"` +} + +// 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"` +} + +// 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 { + Role_name string `json:"role_name,omitempty"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Mirror_url string `json:"mirror_url"` + Issues_url string `json:"issues_url"` + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Git_tags_url string `json:"git_tags_url"` + Git_commits_url string `json:"git_commits_url"` + Statuses_url string `json:"statuses_url"` + Issue_events_url string `json:"issue_events_url"` + Network_count int `json:"network_count,omitempty"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Releases_url string `json:"releases_url"` + Languages_url string `json:"languages_url"` + Master_branch string `json:"master_branch,omitempty"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Topics []string `json:"topics,omitempty"` + Pushed_at string `json:"pushed_at"` + Subscribers_url string `json:"subscribers_url"` + Commits_url string `json:"commits_url"` + Labels_url string `json:"labels_url"` + Merges_url string `json:"merges_url"` + Html_url string `json:"html_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Private bool `json:"private"` // Whether the repository is private or public. + Homepage string `json:"homepage"` + Downloads_url string `json:"downloads_url"` + Ssh_url string `json:"ssh_url"` + License GeneratedType `json:"license"` // License Simple + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Contributors_url string `json:"contributors_url"` + Stargazers_count int `json:"stargazers_count"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Stargazers_url string `json:"stargazers_url"` + Notifications_url string `json:"notifications_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Git_refs_url string `json:"git_refs_url"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Trees_url string `json:"trees_url"` + Keys_url string `json:"keys_url"` + Clone_url string `json:"clone_url"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Deployments_url string `json:"deployments_url"` + Forks int `json:"forks"` + Forks_url string `json:"forks_url"` + Url string `json:"url"` + Forks_count int `json:"forks_count"` + Blobs_url string `json:"blobs_url"` + Collaborators_url string `json:"collaborators_url"` + Assignees_url string `json:"assignees_url"` + Description string `json:"description"` + Open_issues int `json:"open_issues"` + Teams_url string `json:"teams_url"` + Fork bool `json:"fork"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Created_at string `json:"created_at"` + Svn_url string `json:"svn_url"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Has_pages bool `json:"has_pages"` + Comments_url string `json:"comments_url"` + Open_issues_count int `json:"open_issues_count"` + Archive_url string `json:"archive_url"` + Full_name string `json:"full_name"` + Pulls_url string `json:"pulls_url"` + Id int `json:"id"` // Unique identifier of the repository + Branches_url string `json:"branches_url"` + Events_url string `json:"events_url"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Watchers int `json:"watchers"` + Tags_url string `json:"tags_url"` + Language string `json:"language"` + Subscription_url string `json:"subscription_url"` + Size int `json:"size"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Updated_at string `json:"updated_at"` + Git_url string `json:"git_url"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Watchers_count int `json:"watchers_count"` + Compare_url string `json:"compare_url"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Milestones_url string `json:"milestones_url"` + Node_id string `json:"node_id"` + Contents_url string `json:"contents_url"` + Name string `json:"name"` // The name of the repository. + 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. + Hooks_url string `json:"hooks_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"` // 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)." + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Previous_column_name string `json:"previous_column_name,omitempty"` + Project_id int `json:"project_id"` + Project_url string `json:"project_url"` + Url string `json:"url"` + Column_name string `json:"column_name"` +} + +// 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 { + Id string `json:"id"` // The unique identifier of the network settings resource. + 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. +} + +// Hook represents the Hook schema from the OpenAPI specification +type Hook struct { + Test_url string `json:"test_url"` + Config GeneratedType `json:"config"` // Configuration object of the webhook + Ping_url string `json:"ping_url"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Events []string `json:"events"` // Determines what events the hook is triggered for. Default: ['push']. + Id int `json:"id"` // Unique identifier of the webhook. + TypeField string `json:"type"` + Created_at string `json:"created_at"` + Deliveries_url string `json:"deliveries_url,omitempty"` + Last_response GeneratedType `json:"last_response"` + Name string `json:"name"` // The name of a valid service, use 'web' for a webhook. + Active bool `json:"active"` // Determines whether the hook is actually triggered on pushes. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Starred_at string `json:"starred_at"` + Repo Repository `json:"repo"` // A repository on GitHub. +} + +// 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. +} + +// Webhooksworkflow represents the Webhooksworkflow schema from the OpenAPI specification +type Webhooksworkflow struct { + Url string `json:"url"` + Name string `json:"name"` + Node_id string `json:"node_id"` + Path string `json:"path"` + State string `json:"state"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Badge_url string `json:"badge_url"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Member Webhooksuser `json:"member"` + 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. + Scope string `json:"scope"` // The scope of the membership. Currently, can only be `team`. + 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. + Team Webhooksteam `json:"team"` // Groups of organization members that gives permissions on specified repositories. + Sender map[string]interface{} `json:"sender"` + 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 { + 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. +} + +// 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 { + 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. + Action string `json:"action"` +} + +// Migration represents the Migration schema from the OpenAPI specification +type Migration struct { + Guid string `json:"guid"` + Exclude_releases bool `json:"exclude_releases"` + Archive_url string `json:"archive_url,omitempty"` + Exclude_attachments bool `json:"exclude_attachments"` + Lock_repositories bool `json:"lock_repositories"` + Updated_at string `json:"updated_at"` + Exclude_git_data bool `json:"exclude_git_data"` + 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_metadata bool `json:"exclude_metadata"` + Id int64 `json:"id"` + Node_id string `json:"node_id"` + Org_metadata_only bool `json:"org_metadata_only"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Created_at string `json:"created_at"` + State string `json:"state"` + Url string `json:"url"` + Exclude_owner_projects bool `json:"exclude_owner_projects"` + Repositories []Repository `json:"repositories"` // The repositories included in the migration. Only returned for export migrations. +} + +// 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. +} + +// 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 { + 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. + 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. +} + +// 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 { + Label Webhookslabel `json:"label,omitempty"` + Number int `json:"number"` // The pull request number. + Pull_request map[string]interface{} `json:"pull_request"` + 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. + 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"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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). + Releases_url string `json:"releases_url"` + Issue_comment_url string `json:"issue_comment_url"` + Code_search_index_status map[string]interface{} `json:"code_search_index_status,omitempty"` // The status of the code search index for this repository + Git_tags_url string `json:"git_tags_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. + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Trees_url string `json:"trees_url"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + Name string `json:"name"` // The name of the repository. + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Svn_url string `json:"svn_url"` + Watchers_count int `json:"watchers_count"` + Ssh_url string `json:"ssh_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Pushed_at string `json:"pushed_at"` + Has_pages bool `json:"has_pages"` + Milestones_url string `json:"milestones_url"` + Notifications_url string `json:"notifications_url"` + Watchers int `json:"watchers"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Mirror_url string `json:"mirror_url"` + License GeneratedType `json:"license"` // License Simple + Branches_url string `json:"branches_url"` + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Node_id string `json:"node_id"` + Stargazers_count int `json:"stargazers_count"` + Keys_url string `json:"keys_url"` + Starred_at string `json:"starred_at,omitempty"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Topics []string `json:"topics,omitempty"` + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Git_url string `json:"git_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + 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. + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + Commits_url string `json:"commits_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Stargazers_url string `json:"stargazers_url"` + Clone_url string `json:"clone_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Languages_url string `json:"languages_url"` + Labels_url string `json:"labels_url"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Collaborators_url string `json:"collaborators_url"` + Full_name string `json:"full_name"` + Html_url string `json:"html_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Assignees_url string `json:"assignees_url"` + Forks_count int `json:"forks_count"` + Issues_url string `json:"issues_url"` + Tags_url string `json:"tags_url"` + Compare_url string `json:"compare_url"` + Git_commits_url string `json:"git_commits_url"` + Blobs_url string `json:"blobs_url"` + Open_issues int `json:"open_issues"` + Fork bool `json:"fork"` + Id int64 `json:"id"` // Unique identifier of the repository + Language string `json:"language"` + Teams_url string `json:"teams_url"` + Downloads_url string `json:"downloads_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). + Subscription_url string `json:"subscription_url"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Statuses_url string `json:"statuses_url"` + Merges_url string `json:"merges_url"` + Homepage string `json:"homepage"` + 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. + 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. + Private bool `json:"private"` // Whether the repository is private or public. + Contributors_url string `json:"contributors_url"` + Issue_events_url string `json:"issue_events_url"` + Comments_url string `json:"comments_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. + Open_issues_count int `json:"open_issues_count"` + Hooks_url string `json:"hooks_url"` + Pulls_url string `json:"pulls_url"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Forks_url string `json:"forks_url"` + Events_url string `json:"events_url"` + Master_branch string `json:"master_branch,omitempty"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Archive_url string `json:"archive_url"` + Description string `json:"description"` + Contents_url string `json:"contents_url"` + Forks int `json:"forks"` + Git_refs_url string `json:"git_refs_url"` + Subscribers_url string `json:"subscribers_url"` + Deployments_url string `json:"deployments_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + 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 + 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 + 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 + 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. + Source string `json:"source"` // What type of content was scanned + Started_at string `json:"started_at"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + TypeField string `json:"type"` // What type of scan was completed + Action string `json:"action"` + Completed_at string `json:"completed_at"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + 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 { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Id int `json:"id"` // Unique identifier of the classroom. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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" + TypeField string `json:"type,omitempty"` // The type of scan +} + +// 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)." + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Created_on string `json:"created_on"` // The time at which the network configuration was created, in ISO 8601 format. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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. +} + +// Webhooksanswer represents the Webhooksanswer schema from the OpenAPI specification +type Webhooksanswer struct { + Parent_id interface{} `json:"parent_id"` + Child_comment_count int `json:"child_comment_count"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + Repository_url string `json:"repository_url"` + Body string `json:"body"` + Created_at string `json:"created_at"` + Discussion_id int `json:"discussion_id"` + Id int `json:"id"` + User map[string]interface{} `json:"user"` + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Html_url string `json:"html_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Context string `json:"context"` + Commit map[string]interface{} `json:"commit"` + Description string `json:"description"` // The optional human-readable description added to the status. + State string `json:"state"` // The new state. Can be `pending`, `success`, `failure`, or `error`. + Sha string `json:"sha"` // The Commit SHA. + 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. + 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. + Name string `json:"name"` + 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. + 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)." + Target_url string `json:"target_url"` // The optional link added to the status. + Avatar_url string `json:"avatar_url,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"` // 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 { + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + 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)." + 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. + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Action string `json:"action"` + Comment string `json:"comment,omitempty"` + 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 GeneratedType `json:"sender"` // A GitHub user. + Since string `json:"since"` + 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)." + Workflow_job_run Webhooksworkflowjobrun `json:"workflow_job_run,omitempty"` + Workflow_run map[string]interface{} `json:"workflow_run"` + Approver Webhooksapprover `json:"approver,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. + Reviewers []map[string]interface{} `json:"reviewers,omitempty"` + Workflow_job_runs []map[string]interface{} `json:"workflow_job_runs,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Reason string `json:"reason,omitempty"` // Reason for restriction + Oid string `json:"oid"` // Full or abbreviated commit hash to reject +} + +// 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 { + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// 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 { + 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"` + 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`. +} + +// 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Annotation_level string `json:"annotation_level"` + Message string `json:"message"` + Raw_details string `json:"raw_details"` + Start_column int `json:"start_column"` + Title string `json:"title"` + Blob_href string `json:"blob_href"` + End_line int `json:"end_line"` + End_column int `json:"end_column"` + Path string `json:"path"` + Start_line int `json:"start_line"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// 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 { + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` + Url string `json:"url"` + Html_url string `json:"html_url"` + Key string `json:"key"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Key string `json:"key"` + Name string `json:"name"` + Url string `json:"url"` + Html_url string `json:"html_url"` +} + +// Snapshot represents the Snapshot schema from the OpenAPI specification +type Snapshot struct { + 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. + 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. +} + +// 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 Webhooksrelease `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 { + Action string `json:"action"` + Changes map[string]interface{} `json:"changes,omitempty"` + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Object map[string]interface{} `json:"object"` + Ref string `json:"ref"` + Url string `json:"url"` +} + +// Feed represents the Feed schema from the OpenAPI specification +type Feed struct { + Current_user_organization_url string `json:"current_user_organization_url,omitempty"` + Security_advisories_url string `json:"security_advisories_url,omitempty"` + Current_user_actor_url string `json:"current_user_actor_url,omitempty"` + Current_user_organization_urls []string `json:"current_user_organization_urls,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. + User_url string `json:"user_url"` + Current_user_public_url string `json:"current_user_public_url,omitempty"` + Repository_discussions_url string `json:"repository_discussions_url,omitempty"` // A feed of discussions for a given repository. + Links map[string]interface{} `json:"_links"` + Timeline_url string `json:"timeline_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Count int `json:"count"` + Path string `json:"path"` + Title string `json:"title"` + Uniques int `json:"uniques"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Organization GeneratedType `json:"organization"` // A GitHub organization. + Organization_url string `json:"organization_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Events_url string `json:"events_url"` + Id int `json:"id"` + Name string `json:"name,omitempty"` + Members_allowed_repository_creation_type string `json:"members_allowed_repository_creation_type,omitempty"` + Email string `json:"email,omitempty"` + Members_url string `json:"members_url"` + Description string `json:"description"` + Members_can_fork_private_repositories bool `json:"members_can_fork_private_repositories,omitempty"` + Twitter_username string `json:"twitter_username,omitempty"` + Html_url string `json:"html_url"` + Updated_at string `json:"updated_at"` + Archived_at string `json:"archived_at"` + Public_members_url string `json:"public_members_url"` + Blog string `json:"blog,omitempty"` + Members_can_create_private_pages bool `json:"members_can_create_private_pages,omitempty"` + Public_repos int `json:"public_repos"` + Members_can_create_internal_repositories bool `json:"members_can_create_internal_repositories,omitempty"` + Owned_private_repos int `json:"owned_private_repos,omitempty"` + Has_organization_projects bool `json:"has_organization_projects"` + Following int `json:"following"` + Default_repository_permission string `json:"default_repository_permission,omitempty"` + Total_private_repos int `json:"total_private_repos,omitempty"` + Followers int `json:"followers"` + Public_gists int `json:"public_gists"` + Members_can_create_pages bool `json:"members_can_create_pages,omitempty"` + Plan map[string]interface{} `json:"plan,omitempty"` + Collaborators int `json:"collaborators,omitempty"` + Has_repository_projects bool `json:"has_repository_projects"` + Members_can_create_private_repositories bool `json:"members_can_create_private_repositories,omitempty"` + Repos_url string `json:"repos_url"` + TypeField string `json:"type"` + Company string `json:"company,omitempty"` + Location string `json:"location,omitempty"` + Private_gists int `json:"private_gists,omitempty"` + Node_id string `json:"node_id"` + Issues_url string `json:"issues_url"` + Is_verified bool `json:"is_verified,omitempty"` + Two_factor_requirement_enabled bool `json:"two_factor_requirement_enabled,omitempty"` + Hooks_url string `json:"hooks_url"` + Members_can_create_public_repositories bool `json:"members_can_create_public_repositories,omitempty"` + Url string `json:"url"` + Login string `json:"login"` + Avatar_url string `json:"avatar_url"` + Billing_email string `json:"billing_email,omitempty"` + Members_can_create_repositories bool `json:"members_can_create_repositories,omitempty"` + Disk_usage int `json:"disk_usage,omitempty"` + Members_can_create_public_pages bool `json:"members_can_create_public_pages,omitempty"` + Created_at string `json:"created_at"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Source string `json:"source"` // The image provider. +} + +// 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 { + Event string `json:"event"` + Id int `json:"id"` + Node_id string `json:"node_id"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Commit_id string `json:"commit_id"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Head_commit GeneratedType `json:"head_commit"` // A commit. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + 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. + Created_at string `json:"created_at"` + Id int `json:"id"` // Unique identifier of the issue comment + Updated_at string `json:"updated_at"` + Html_url string `json:"html_url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Body_html string `json:"body_html,omitempty"` + Event string `json:"event"` + Issue_url string `json:"issue_url"` + Body_text string `json:"body_text,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. + Url string `json:"url"` // URL for the issue comment + Body string `json:"body,omitempty"` // Contents of the issue comment + 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 { + 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 { + Starred_url string `json:"starred_url"` + Plan map[string]interface{} `json:"plan,omitempty"` + Public_gists int `json:"public_gists"` + Blog string `json:"blog"` + Node_id string `json:"node_id"` + Name string `json:"name"` + Updated_at string `json:"updated_at"` + Bio string `json:"bio"` + Total_private_repos int `json:"total_private_repos"` + Avatar_url string `json:"avatar_url"` + Private_gists int `json:"private_gists"` + Location string `json:"location"` + Site_admin bool `json:"site_admin"` + Ldap_dn string `json:"ldap_dn,omitempty"` + Followers_url string `json:"followers_url"` + Business_plus bool `json:"business_plus,omitempty"` + Created_at string `json:"created_at"` + Company string `json:"company"` + Url string `json:"url"` + Two_factor_authentication bool `json:"two_factor_authentication"` + Following int `json:"following"` + Hireable bool `json:"hireable"` + Html_url string `json:"html_url"` + Followers int `json:"followers"` + Disk_usage int `json:"disk_usage"` + Events_url string `json:"events_url"` + TypeField string `json:"type"` + Public_repos int `json:"public_repos"` + Subscriptions_url string `json:"subscriptions_url"` + Gists_url string `json:"gists_url"` + Received_events_url string `json:"received_events_url"` + User_view_type string `json:"user_view_type,omitempty"` + Following_url string `json:"following_url"` + Gravatar_id string `json:"gravatar_id"` + Id int64 `json:"id"` + Twitter_username string `json:"twitter_username,omitempty"` + Notification_email string `json:"notification_email,omitempty"` + Login string `json:"login"` + Repos_url string `json:"repos_url"` + Collaborators int `json:"collaborators"` + Email string `json:"email"` + Organizations_url string `json:"organizations_url"` + Owned_private_repos int `json:"owned_private_repos"` +} + +// 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 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)." + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Event string `json:"event,omitempty"` + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Sha string `json:"sha"` // SHA for the commit + Committer map[string]interface{} `json:"committer"` // Identifying information for the git-user + Url string `json:"url"` + Verification map[string]interface{} `json:"verification"` + Message string `json:"message"` // Message describing the purpose of the commit + Tree map[string]interface{} `json:"tree"` + Author map[string]interface{} `json:"author"` // Identifying information for the git-user + Parents []map[string]interface{} `json:"parents"` +} + +// 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 +} + +// Enterprise represents the Enterprise schema from the OpenAPI specification +type Enterprise struct { + Description string `json:"description,omitempty"` // A short description of the enterprise. + Id int `json:"id"` // Unique identifier of the enterprise + Node_id string `json:"node_id"` + Slug string `json:"slug"` // The slug url identifier for the enterprise. + Updated_at string `json:"updated_at"` + Html_url string `json:"html_url"` + Name string `json:"name"` // The name of the enterprise. + Website_url string `json:"website_url,omitempty"` // The enterprise's website URL. + Avatar_url string `json:"avatar_url"` + Created_at string `json:"created_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sponsorship Webhookssponsorship `json:"sponsorship"` + 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. +} + +// 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 { + 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 { + Identifiers []map[string]interface{} `json:"identifiers"` + Cvss map[string]interface{} `json:"cvss"` + References []string `json:"references"` + Repository_advisory_url string `json:"repository_advisory_url"` // The API URL for the repository advisory. + Html_url string `json:"html_url"` // The URL for the advisory. + Source_code_location string `json:"source_code_location"` // The URL of the advisory's source code. + Ghsa_id string `json:"ghsa_id"` // The GitHub Security Advisory ID. + Cwes []map[string]interface{} `json:"cwes"` + Withdrawn_at string `json:"withdrawn_at"` // The date and time of when the advisory was withdrawn, in ISO 8601 format. + 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. + Updated_at string `json:"updated_at"` // The date and time of when the advisory was last updated, in ISO 8601 format. + Credits []map[string]interface{} `json:"credits"` // The users who contributed to the advisory. + Github_reviewed_at string `json:"github_reviewed_at"` // The date and time of when the advisory was reviewed by GitHub, in ISO 8601 format. + Published_at string `json:"published_at"` // The date and time of when the advisory was published, in ISO 8601 format. + Vulnerabilities []Vulnerability `json:"vulnerabilities"` // The products and respective version ranges affected by the advisory. + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + Epss GeneratedType `json:"epss,omitempty"` // The EPSS scores as calculated by the [Exploit Prediction Scoring System](https://www.first.org/epss). + TypeField string `json:"type"` // The type of advisory. + Severity string `json:"severity"` // The severity of the advisory. + Url string `json:"url"` // The API URL for the advisory. + Cve_id string `json:"cve_id"` // The Common Vulnerabilities and Exposures (CVE) ID. + Summary string `json:"summary"` // A short summary of the advisory. + Description string `json:"description"` // A detailed description of what the advisory entails. +} + +// 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)." + 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. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + End_column int `json:"end_column,omitempty"` + 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"` +} + +// 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 { + Delivered_at string `json:"delivered_at"` // Time when the delivery was delivered. + Action string `json:"action"` // The type of activity for the event that triggered the delivery. + Id int `json:"id"` // Unique identifier of the delivery. + Url string `json:"url,omitempty"` // The URL target of the delivery. + Installation_id int `json:"installation_id"` // The id of the GitHub App installation associated with this event. + Request map[string]interface{} `json:"request"` + Response map[string]interface{} `json:"response"` + Status string `json:"status"` // Description of the status of the attempted delivery + Guid string `json:"guid"` // Unique identifier for the event (shared with all deliveries for all webhooks that subscribe to this event). + Duration float64 `json:"duration"` // Time spent delivering. + Redelivery bool `json:"redelivery"` // Whether the delivery is a redelivery. + Repository_id int `json:"repository_id"` // The id of the repository associated with this event. + Throttled_at string `json:"throttled_at,omitempty"` // Time when the webhook delivery was throttled. + Status_code int `json:"status_code"` // Status code received when delivery was made. + Event string `json:"event"` // The event that triggered the delivery. +} + +// 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. + 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. +} + +// 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"` + 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)." +} + +// 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 { + Cwe_ids []string `json:"cwe_ids,omitempty"` // A list of Common Weakness Enumeration (CWE) IDs. + Severity string `json:"severity,omitempty"` // The severity of the advisory. You must choose between setting this field or `cvss_vector_string`. + Vulnerabilities []map[string]interface{} `json:"vulnerabilities,omitempty"` // A product affected by the vulnerability detailed in a repository security advisory. + Collaborating_teams []string `json:"collaborating_teams,omitempty"` // A list of team slugs which have been granted write access to the advisory. + State string `json:"state,omitempty"` // The state of the advisory. + Cve_id string `json:"cve_id,omitempty"` // The Common Vulnerabilities and Exposures (CVE) ID. + 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`. + Summary string `json:"summary,omitempty"` // A short summary of the 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. + Description string `json:"description,omitempty"` // A detailed description of what the advisory impacts. +} + +// 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 { + 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"` + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Author_association string `json:"author_association"` // How the author is associated with the repository. + Pull_request_url string `json:"pull_request_url"` + Submitted_at string `json:"submitted_at,omitempty"` + Body_text string `json:"body_text,omitempty"` + State string `json:"state"` + Body string `json:"body"` // The text of the review. + Html_url string `json:"html_url"` + Id int64 `json:"id"` // Unique identifier of the review + User GeneratedType `json:"user"` // A GitHub user. + Links map[string]interface{} `json:"_links"` + 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`. + Node_id string `json:"node_id"` +} + +// Webhooksissue represents the Webhooksissue schema from the OpenAPI specification +type Webhooksissue struct { + Repository_url string `json:"repository_url"` + Title string `json:"title"` // Title of the issue + Created_at string `json:"created_at"` + Url string `json:"url"` // URL for the issue + Active_lock_reason string `json:"active_lock_reason"` + Draft bool `json:"draft,omitempty"` + Labels_url string `json:"labels_url"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Sub_issues_summary map[string]interface{} `json:"sub_issues_summary,omitempty"` + Timeline_url string `json:"timeline_url,omitempty"` + Milestone map[string]interface{} `json:"milestone"` // A collection of related issues and pull requests. + Node_id string `json:"node_id"` + Number int `json:"number"` + Reactions map[string]interface{} `json:"reactions"` + Events_url string `json:"events_url"` + Closed_at string `json:"closed_at"` + Updated_at string `json:"updated_at"` + Body string `json:"body"` // Contents of the issue + Assignee map[string]interface{} `json:"assignee,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + State_reason string `json:"state_reason,omitempty"` + Comments_url string `json:"comments_url"` + Assignees []map[string]interface{} `json:"assignees"` + Locked bool `json:"locked,omitempty"` + Id int64 `json:"id"` + 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. + Html_url string `json:"html_url"` + User map[string]interface{} `json:"user"` + State string `json:"state,omitempty"` // State of the issue; either 'open' or 'closed' + Labels []map[string]interface{} `json:"labels,omitempty"` + Comments int `json:"comments"` +} + +// 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 { + 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"` + 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Pull_request GeneratedType `json:"pull_request"` + Number int `json:"number"` // The pull request number. + 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)." + 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)." + 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 { + Help_uri string `json:"help_uri,omitempty"` // A link to the documentation 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. + 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. + Security_severity_level string `json:"security_severity_level,omitempty"` // The security severity of the alert. + Tags []string `json:"tags,omitempty"` // A set of tags applicable for the rule. + Description string `json:"description,omitempty"` // A short description of the rule used to detect the alert. + Help string `json:"help,omitempty"` // Detailed documentation for the rule as GitHub Flavored Markdown. +} + +// Installation represents the Installation schema from the OpenAPI specification +type Installation struct { + Repositories_url string `json:"repositories_url"` + Created_at string `json:"created_at"` + Suspended_by GeneratedType `json:"suspended_by"` // A GitHub user. + Has_multiple_single_files bool `json:"has_multiple_single_files,omitempty"` + Suspended_at string `json:"suspended_at"` + Access_tokens_url string `json:"access_tokens_url"` + Html_url string `json:"html_url"` + Single_file_name string `json:"single_file_name"` + App_slug string `json:"app_slug"` + Updated_at string `json:"updated_at"` + Events []string `json:"events"` + Id int `json:"id"` // The ID of the installation. + Account interface{} `json:"account"` + Permissions GeneratedType `json:"permissions"` // The permissions granted to the user access token. + App_id int `json:"app_id"` + Single_file_paths []string `json:"single_file_paths,omitempty"` + Target_type string `json:"target_type"` + Repository_selection string `json:"repository_selection"` // Describe whether all repositories have been selected or there's a selection involved + Target_id int `json:"target_id"` // The ID of the user or organization this token is being scoped to. + Contact_email string `json:"contact_email,omitempty"` +} + +// 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Allow_force_pushes map[string]interface{} `json:"allow_force_pushes,omitempty"` + Enforce_admins GeneratedType `json:"enforce_admins,omitempty"` // Protected Branch Admin Enforced + Url string `json:"url,omitempty"` + Block_creations map[string]interface{} `json:"block_creations,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Protection_url string `json:"protection_url,omitempty"` + Restrictions GeneratedType `json:"restrictions,omitempty"` // Branch Restriction Policy + Required_linear_history map[string]interface{} `json:"required_linear_history,omitempty"` + Required_pull_request_reviews GeneratedType `json:"required_pull_request_reviews,omitempty"` // Protected Branch Pull Request Review + Required_signatures map[string]interface{} `json:"required_signatures,omitempty"` + Allow_deletions map[string]interface{} `json:"allow_deletions,omitempty"` + Required_status_checks GeneratedType `json:"required_status_checks,omitempty"` // Protected Branch Required Status Check + Name string `json:"name,omitempty"` + Required_conversation_resolution map[string]interface{} `json:"required_conversation_resolution,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. + 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. +} + +// 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. + 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. + 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,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. + 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 { + 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 { + 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. + Reason string `json:"reason,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. + 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)." + Pull_request map[string]interface{} `json:"pull_request"` + 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)." + Number int `json:"number"` +} + +// Activity represents the Activity schema from the OpenAPI specification +type Activity struct { + Activity_type string `json:"activity_type"` // The type of the activity that was performed. + Actor GeneratedType `json:"actor"` // A GitHub user. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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. +} + +// 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField string `json:"type"` // The type of credit the user is receiving. + User GeneratedType `json:"user"` // A GitHub user. + State string `json:"state"` // The state of the user's acceptance of the credit. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parent GeneratedType `json:"parent"` // Groups of organization members that gives permissions on specified repositories. + Privacy string `json:"privacy,omitempty"` + Permission string `json:"permission"` + Id int `json:"id"` + Url string `json:"url"` + Assignment string `json:"assignment,omitempty"` // Determines if the team has a direct, indirect, or mixed relationship to a role + Permissions map[string]interface{} `json:"permissions,omitempty"` + Slug string `json:"slug"` + Html_url string `json:"html_url"` + Members_url string `json:"members_url"` + Repositories_url string `json:"repositories_url"` + Name string `json:"name"` + Node_id string `json:"node_id"` + Notification_setting string `json:"notification_setting,omitempty"` + Description string `json:"description"` +} + +// 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. + Repository_advisory GeneratedType `json:"repository_advisory"` // A repository security advisory. + 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 { + 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 { + 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)." + Number int `json:"number"` // The pull request number. + 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)." + Sender GeneratedType `json:"sender"` // A GitHub user. + Pull_request map[string]interface{} `json:"pull_request"` + Before string `json:"before"` + 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"` +} + +// 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 { + 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. +} + +// Webhookspreviousmarketplacepurchase represents the Webhookspreviousmarketplacepurchase schema from the OpenAPI specification +type Webhookspreviousmarketplacepurchase struct { + Account map[string]interface{} `json:"account"` + 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"` +} + +// 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 { + Total_engaged_users int `json:"total_engaged_users,omitempty"` // Total number of users who prompted Copilot Chat on github.com at least once. + Models []map[string]interface{} `json:"models,omitempty"` // List of model metrics for a custom models and the default model. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit_id string `json:"commit_id"` + Id int `json:"id"` + 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"` + Event string `json:"event"` + Label map[string]interface{} `json:"label"` + Actor GeneratedType `json:"actor"` // A GitHub user. +} + +// 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 { + 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 + Repository_selection string `json:"repository_selection,omitempty"` // 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 { + 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"` + Action string `json:"action"` +} + +// 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 { + Total_count int `json:"total_count"` + Confused int `json:"confused"` + Hooray int `json:"hooray"` + Rocket int `json:"rocket"` + Eyes int `json:"eyes"` + Url string `json:"url"` + Field1 int `json:"-1"` + Field1 int `json:"+1"` + Heart int `json:"heart"` + Laugh int `json:"laugh"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Code int `json:"code"` + Message string `json:"message"` + Status string `json:"status"` +} + +// Webhookspullrequest5 represents the Webhookspullrequest5 schema from the OpenAPI specification +type Webhookspullrequest5 struct { + Mergeable bool `json:"mergeable,omitempty"` + Review_comments_url string `json:"review_comments_url"` + Merged_at string `json:"merged_at"` + Rebaseable bool `json:"rebaseable,omitempty"` + Closed_at string `json:"closed_at"` + Draft bool `json:"draft"` // Indicates whether or not the pull request is a draft. + Comments int `json:"comments,omitempty"` + Html_url string `json:"html_url"` + Number int `json:"number"` // Number uniquely identifying the pull request within its repository. + Commits int `json:"commits,omitempty"` + Locked bool `json:"locked"` + Auto_merge map[string]interface{} `json:"auto_merge"` // The status of auto merging a pull request. + User map[string]interface{} `json:"user"` + Head map[string]interface{} `json:"head"` + Merged bool `json:"merged,omitempty"` + Changed_files int `json:"changed_files,omitempty"` + Links map[string]interface{} `json:"_links"` + Title string `json:"title"` // The title of the pull request. + State string `json:"state"` // State of this Pull Request. Either `open` or `closed`. + Body string `json:"body"` + Created_at string `json:"created_at"` + Active_lock_reason string `json:"active_lock_reason"` + Assignee map[string]interface{} `json:"assignee"` + Mergeable_state string `json:"mergeable_state,omitempty"` + Review_comment_url string `json:"review_comment_url"` + Maintainer_can_modify bool `json:"maintainer_can_modify,omitempty"` // Indicates whether maintainers can modify the pull request. + Statuses_url string `json:"statuses_url"` + Issue_url string `json:"issue_url"` + Labels []map[string]interface{} `json:"labels"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Comments_url string `json:"comments_url"` + Milestone map[string]interface{} `json:"milestone"` // A collection of related issues and pull requests. + Deletions int `json:"deletions,omitempty"` + Commits_url string `json:"commits_url"` + Id int `json:"id"` + Diff_url string `json:"diff_url"` + Requested_reviewers []interface{} `json:"requested_reviewers"` + Url string `json:"url"` + Patch_url string `json:"patch_url"` + Assignees []map[string]interface{} `json:"assignees"` + Merged_by map[string]interface{} `json:"merged_by,omitempty"` + Review_comments int `json:"review_comments,omitempty"` + Base map[string]interface{} `json:"base"` + Updated_at string `json:"updated_at"` + Additions int `json:"additions,omitempty"` + Merge_commit_sha string `json:"merge_commit_sha"` + Node_id string `json:"node_id"` + Requested_teams []map[string]interface{} `json:"requested_teams"` +} + +// 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,omitempty"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Deployment GeneratedType `json:"deployment,omitempty"` // A deployment created as the result of an Actions check run from a workflow that references an environment + Details_url string `json:"details_url"` + 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. + Url string `json:"url"` + 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. + Name string `json:"name"` // The name of the check. + Output map[string]interface{} `json:"output"` + Head_sha string `json:"head_sha"` // The SHA of the commit that is being checked. + External_id string `json:"external_id"` + Started_at string `json:"started_at"` + Check_suite map[string]interface{} `json:"check_suite"` + Conclusion string `json:"conclusion"` + Completed_at string `json:"completed_at"` + Id int64 `json:"id"` // The id of the check. + Html_url string `json:"html_url"` + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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. + Client_id string `json:"client_id,omitempty"` + Id int `json:"id"` // Unique identifier of the GitHub app + Permissions map[string]interface{} `json:"permissions"` // The set of permissions for the GitHub app + Description string `json:"description"` + Owner interface{} `json:"owner"` + Updated_at string `json:"updated_at"` + External_url string `json:"external_url"` + Html_url string `json:"html_url"` + Name string `json:"name"` // The name of the GitHub app + Node_id string `json:"node_id"` + Slug string `json:"slug,omitempty"` // The slug name of the GitHub app + Created_at string `json:"created_at"` +} + +// Webhooksreview represents the Webhooksreview schema from the OpenAPI specification +type Webhooksreview struct { + Id int `json:"id"` // Unique identifier of the review + Body string `json:"body"` // The text of the review. + Commit_id string `json:"commit_id"` // A commit SHA for the review. + State string `json:"state"` + Links map[string]interface{} `json:"_links"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Submitted_at string `json:"submitted_at"` + Node_id string `json:"node_id"` + Pull_request_url string `json:"pull_request_url"` + User map[string]interface{} `json:"user"` + Html_url string `json:"html_url"` +} + +// 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 { + 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 { + 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. + Security_advisory Webhookssecurityadvisory `json:"security_advisory"` // The details of the security advisory, including summary, description, and severity. +} + +// 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 { + 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. + Registry_package map[string]interface{} `json:"registry_package"` +} + +// 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 { + 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. + Changes Webhookschanges `json:"changes"` // The changes to the comment. + 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)." + 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"` + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender"` // A GitHub user. + Workflow Webhooksworkflow `json:"workflow"` + 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. + Workflow_run map[string]interface{} `json:"workflow_run"` + Deployment map[string]interface{} `json:"deployment"` // The [deployment](https://docs.github.com/rest/deployments/deployments#list-deployments). + 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 { + 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)." + 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. +} + +// Webhooksissue2 represents the Webhooksissue2 schema from the OpenAPI specification +type Webhooksissue2 struct { + Updated_at string `json:"updated_at"` + Node_id string `json:"node_id"` + Assignees []map[string]interface{} `json:"assignees"` + Url string `json:"url"` // URL for the issue + Title string `json:"title"` // Title of the issue + Reactions map[string]interface{} `json:"reactions"` + Milestone map[string]interface{} `json:"milestone"` // A collection of related issues and pull requests. + Id int64 `json:"id"` + Labels_url string `json:"labels_url"` + Repository_url string `json:"repository_url"` + Sub_issues_summary map[string]interface{} `json:"sub_issues_summary,omitempty"` + Created_at string `json:"created_at"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Comments int `json:"comments"` + Comments_url string `json:"comments_url"` + Draft bool `json:"draft,omitempty"` + Labels []map[string]interface{} `json:"labels,omitempty"` + State string `json:"state,omitempty"` // State of the issue; either 'open' or 'closed' + Body string `json:"body"` // Contents of the issue + Html_url string `json:"html_url"` + 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"` + Closed_at string `json:"closed_at"` + State_reason string `json:"state_reason,omitempty"` + User map[string]interface{} `json:"user"` + Locked bool `json:"locked,omitempty"` + Active_lock_reason string `json:"active_lock_reason"` + Timeline_url string `json:"timeline_url,omitempty"` + Events_url string `json:"events_url"` + Number int `json:"number"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Html_url string `json:"html_url,omitempty"` + Location GeneratedType `json:"location,omitempty"` // Describe a region within a file for the alert. + Ref string `json:"ref,omitempty"` // The Git reference, formatted as `refs/pull//merge`, `refs/pull//head`, `refs/heads/` or simply ``. + 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. + Message map[string]interface{} `json:"message,omitempty"` + 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. + 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"` + State string `json:"state,omitempty"` // State of a code scanning alert. +} + +// 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 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 { + 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,omitempty"` + Check_run GeneratedType `json:"check_run"` // A check performed on the code of a given code change +} + +// 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 { + 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 { + 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. +} + +// Webhooksmarketplacepurchase represents the Webhooksmarketplacepurchase schema from the OpenAPI specification +type Webhooksmarketplacepurchase struct { + 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"` + Account map[string]interface{} `json:"account"` + Billing_cycle string `json:"billing_cycle"` + Free_trial_ends_on string `json:"free_trial_ends_on"` +} + +// 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Parents []map[string]interface{} `json:"parents"` + Verification map[string]interface{} `json:"verification"` + Committer map[string]interface{} `json:"committer"` // Identifying information for the git-user + Sha string `json:"sha"` // SHA for the commit + Tree map[string]interface{} `json:"tree"` + Message string `json:"message"` // Message describing the purpose of the commit + Node_id string `json:"node_id"` + Url string `json:"url"` + Author map[string]interface{} `json:"author"` // Identifying information for the git-user + Html_url string `json:"html_url"` +} + +// 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. + 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 { + Ref string `json:"ref,omitempty"` // The ref name that the evaluation ran on. + Repository_name string `json:"repository_name,omitempty"` // The name of the repository without the `.git` extension. + Rule_evaluations []map[string]interface{} `json:"rule_evaluations,omitempty"` // Details on the evaluated rules. + Actor_id int `json:"actor_id,omitempty"` // The number that identifies the user. + 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. + Id int `json:"id,omitempty"` // The unique identifier of the rule insight. + Pushed_at string `json:"pushed_at,omitempty"` + Repository_id int `json:"repository_id,omitempty"` // The ID of the repository associated with the rule evaluation. + 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. + Result string `json:"result,omitempty"` // The result of the rule evaluations for rules with the `active` enforcement status. + Before_sha string `json:"before_sha,omitempty"` // The first commit sha before the push evaluation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Count int `json:"count"` + Uniques int `json:"uniques"` + Clones []Traffic `json:"clones"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Members_url string `json:"members_url"` + Repositories_url string `json:"repositories_url"` + Slug string `json:"slug"` + 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 + 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"` + Privacy string `json:"privacy,omitempty"` // The level of privacy this team should have + Html_url string `json:"html_url"` + Id int `json:"id"` // Unique identifier of the team + Description string `json:"description"` // Description of the team +} + +// 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 { + 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"` + 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 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 { + Hooks_url string `json:"hooks_url"` + Id int `json:"id"` + Public_members_url string `json:"public_members_url"` + Repos_url string `json:"repos_url"` + Description string `json:"description"` + Login string `json:"login"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` + Members_url string `json:"members_url"` + Events_url string `json:"events_url"` + Issues_url string `json:"issues_url"` + Node_id string `json:"node_id"` +} + +// 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 { + 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 { + Updated_at string `json:"updated_at"` // The date and time the campaign was last updated, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Created_at string `json:"created_at"` // The date and time the campaign was created, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Published_at string `json:"published_at,omitempty"` // The date and time the campaign was published, in ISO 8601 format':' YYYY-MM-DDTHH:MM:SSZ. + Description string `json:"description"` // The campaign description + 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. + 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 + Alert_stats map[string]interface{} `json:"alert_stats,omitempty"` + Managers []GeneratedType `json:"managers"` // The campaign managers + State string `json:"state"` // Indicates whether a campaign is open or closed + Team_managers []Team `json:"team_managers,omitempty"` // The campaign team managers +} + +// 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 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 Webhooksuser `json:"requester,omitempty"` +} + +// 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`. +} + +// Metadata represents the Metadata schema from the OpenAPI specification +type Metadata struct { +} + +// 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 { + 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)." + 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 { + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_id string `json:"commit_id"` + Id int `json:"id"` + Requested_team Team `json:"requested_team,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Created_at string `json:"created_at"` + 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. + Requested_reviewer GeneratedType `json:"requested_reviewer,omitempty"` // A GitHub user. + Event string `json:"event"` + Review_requester GeneratedType `json:"review_requester"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url,omitempty"` // The URL of the configuration + Code_scanning_default_setup string `json:"code_scanning_default_setup,omitempty"` // The enablement status of code scanning default setup + Secret_scanning string `json:"secret_scanning,omitempty"` // The enablement status of secret scanning + Html_url string `json:"html_url,omitempty"` // The URL of the configuration + Secret_scanning_delegated_bypass string `json:"secret_scanning_delegated_bypass,omitempty"` // The enablement status of secret scanning delegated bypass + Secret_scanning_non_provider_patterns string `json:"secret_scanning_non_provider_patterns,omitempty"` // The enablement status of secret scanning non-provider patterns + Secret_scanning_validity_checks string `json:"secret_scanning_validity_checks,omitempty"` // The enablement status of secret scanning validity checks + Code_scanning_default_setup_options map[string]interface{} `json:"code_scanning_default_setup_options,omitempty"` // Feature options for code scanning default setup + Dependabot_alerts string `json:"dependabot_alerts,omitempty"` // The enablement status of Dependabot alerts + Secret_scanning_delegated_alert_dismissal string `json:"secret_scanning_delegated_alert_dismissal,omitempty"` // The enablement status of secret scanning delegated alert dismissal + Code_scanning_options map[string]interface{} `json:"code_scanning_options,omitempty"` // Feature options for code scanning + Private_vulnerability_reporting string `json:"private_vulnerability_reporting,omitempty"` // The enablement status of private vulnerability reporting + Updated_at string `json:"updated_at,omitempty"` + Code_scanning_delegated_alert_dismissal string `json:"code_scanning_delegated_alert_dismissal,omitempty"` // The enablement status of code scanning delegated alert dismissal + Dependabot_security_updates string `json:"dependabot_security_updates,omitempty"` // The enablement status of Dependabot security updates + Dependency_graph string `json:"dependency_graph,omitempty"` // The enablement status of Dependency Graph + Created_at string `json:"created_at,omitempty"` + Enforcement string `json:"enforcement,omitempty"` // The enforcement status for a security configuration + Secret_scanning_delegated_bypass_options map[string]interface{} `json:"secret_scanning_delegated_bypass_options,omitempty"` // Feature options for secret scanning delegated bypass + Description string `json:"description,omitempty"` // A description of the code security configuration + Secret_scanning_generic_secrets string `json:"secret_scanning_generic_secrets,omitempty"` // The enablement status of Copilot secret scanning + Secret_scanning_push_protection string `json:"secret_scanning_push_protection,omitempty"` // The enablement status of secret scanning push protection + Advanced_security string `json:"advanced_security,omitempty"` // The enablement status of GitHub Advanced Security + Dependency_graph_autosubmit_action string `json:"dependency_graph_autosubmit_action,omitempty"` // The enablement status of Automatic dependency submission + Dependency_graph_autosubmit_action_options map[string]interface{} `json:"dependency_graph_autosubmit_action_options,omitempty"` // Feature options for Automatic dependency submission + Id int `json:"id,omitempty"` // The ID of the code security configuration + Name string `json:"name,omitempty"` // The name of the code security configuration. Must be unique within the organization. + Target_type string `json:"target_type,omitempty"` // The type of the code security configuration. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Comments_url string `json:"comments_url"` + Body_html string `json:"body_html"` + Updated_at string `json:"updated_at"` + Html_url string `json:"html_url"` + Body string `json:"body"` // The main text of the discussion. + Reactions GeneratedType `json:"reactions,omitempty"` + Created_at string `json:"created_at"` + Number int `json:"number"` // The unique sequence number of a team discussion. + Pinned bool `json:"pinned"` // Whether or not this discussion should be pinned for easy retrieval. + Team_url string `json:"team_url"` + Title string `json:"title"` // The title of the discussion. + Comments_count int `json:"comments_count"` + Last_edited_at string `json:"last_edited_at"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Private bool `json:"private"` // Whether or not this discussion should be restricted to team members and organization owners. + Author GeneratedType `json:"author"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Content_node_id string `json:"content_node_id"` + Created_at string `json:"created_at"` + Id float64 `json:"id"` + Project_node_id string `json:"project_node_id,omitempty"` + Node_id string `json:"node_id,omitempty"` + Content_type string `json:"content_type"` // The type of content tracked in a project item + Creator GeneratedType `json:"creator,omitempty"` // A GitHub user. + Updated_at string `json:"updated_at"` + Archived_at string `json:"archived_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + 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. + 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 { + 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 { + 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. + 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. +} + +// 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 { + Repos_url string `json:"repos_url"` + Description string `json:"description"` + Members_url string `json:"members_url"` + Node_id string `json:"node_id"` + Public_members_url string `json:"public_members_url"` + Events_url string `json:"events_url"` + Avatar_url string `json:"avatar_url"` + Issues_url string `json:"issues_url"` + Login string `json:"login"` + Url string `json:"url"` + Hooks_url string `json:"hooks_url"` + Id int `json:"id"` +} + +// 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 { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// Contributor represents the Contributor schema from the OpenAPI specification +type Contributor struct { + Gists_url string `json:"gists_url,omitempty"` + Id int `json:"id,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Login string `json:"login,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Contributions int `json:"contributions"` + Repos_url string `json:"repos_url,omitempty"` + Email string `json:"email,omitempty"` + Url string `json:"url,omitempty"` + Node_id string `json:"node_id,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Events_url string `json:"events_url,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + TypeField string `json:"type"` + Name string `json:"name,omitempty"` + Followers_url string `json:"followers_url,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 { + Remote_name string `json:"remote_name"` + Url string `json:"url"` + Email string `json:"email"` + Id int `json:"id"` + Import_url string `json:"import_url"` + Name string `json:"name"` + Remote_id string `json:"remote_id"` +} + +// 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 { + 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"` + 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)." +} + +// 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action"` + 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. +} + +// 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 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Expires_at string `json:"expires_at,omitempty"` + State string `json:"state"` + Description string `json:"description"` + Domains []string `json:"domains"` // Array of the domain set and its alternate name (if it is configured) +} + +// 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 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)." + 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 { + 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. + Commit_id string `json:"commit_id"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Dismissed_review map[string]interface{} `json:"dismissed_review"` + Id int `json:"id"` +} + +// 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"` + 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 { + 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit_id string `json:"commit_id"` + Assignee GeneratedType `json:"assignee,omitempty"` // A GitHub user. + Milestone GeneratedType `json:"milestone,omitempty"` // Issue Event Milestone + Rename GeneratedType `json:"rename,omitempty"` // Issue Event Rename + Author_association string `json:"author_association,omitempty"` // How the author is associated with the repository. + Issue GeneratedType `json:"issue,omitempty"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Requested_team Team `json:"requested_team,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Url string `json:"url"` + Assigner GeneratedType `json:"assigner,omitempty"` // A GitHub user. + Node_id string `json:"node_id"` + Project_card GeneratedType `json:"project_card,omitempty"` // Issue Event Project Card + Created_at string `json:"created_at"` + Requested_reviewer GeneratedType `json:"requested_reviewer,omitempty"` // A GitHub user. + 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. + Lock_reason string `json:"lock_reason,omitempty"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Dismissed_review GeneratedType `json:"dismissed_review,omitempty"` + Label GeneratedType `json:"label,omitempty"` // Issue Event Label + Commit_url string `json:"commit_url"` + Review_requester GeneratedType `json:"review_requester,omitempty"` // A GitHub user. + Id int64 `json:"id"` + Event string `json:"event"` +} + +// 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 { + 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 { + Updated_at string `json:"updated_at"` + Actor GeneratedType `json:"actor,omitempty"` // A GitHub user. + Created_at string `json:"created_at"` + Event string `json:"event"` + Source map[string]interface{} `json:"source"` +} + +// Repository represents the Repository schema from the OpenAPI specification +type Repository struct { + Trees_url string `json:"trees_url"` + Commits_url string `json:"commits_url"` + Updated_at string `json:"updated_at"` + Languages_url string `json:"languages_url"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Name string `json:"name"` // The name of the repository. + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Open_issues int `json:"open_issues"` + Subscribers_url string `json:"subscribers_url"` + Git_commits_url string `json:"git_commits_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Default_branch string `json:"default_branch"` // The default branch of the repository. + Html_url string `json:"html_url"` + Code_search_index_status map[string]interface{} `json:"code_search_index_status,omitempty"` // The status of the code search index for this repository + Master_branch string `json:"master_branch,omitempty"` + Issue_comment_url string `json:"issue_comment_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. + Svn_url string `json:"svn_url"` + Homepage string `json:"homepage"` + Watchers_count int `json:"watchers_count"` + 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. + Stargazers_url string `json:"stargazers_url"` + Labels_url string `json:"labels_url"` + Keys_url string `json:"keys_url"` + Forks_count int `json:"forks_count"` + Forks_url string `json:"forks_url"` + Teams_url string `json:"teams_url"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Contributors_url string `json:"contributors_url"` + Deployments_url string `json:"deployments_url"` + Url string `json:"url"` + Git_refs_url string `json:"git_refs_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Tags_url string `json:"tags_url"` + Node_id string `json:"node_id"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Private bool `json:"private"` // Whether the repository is private or public. + Contents_url string `json:"contents_url"` + Topics []string `json:"topics,omitempty"` + Notifications_url string `json:"notifications_url"` + Compare_url string `json:"compare_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. + Temp_clone_token string `json:"temp_clone_token,omitempty"` + 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 + Starred_at string `json:"starred_at,omitempty"` + 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. + Archive_url string `json:"archive_url"` + Clone_url string `json:"clone_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). + Mirror_url string `json:"mirror_url"` + Stargazers_count int `json:"stargazers_count"` + Language string `json:"language"` + Collaborators_url string `json:"collaborators_url"` + Ssh_url string `json:"ssh_url"` + Assignees_url string `json:"assignees_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + Milestones_url string `json:"milestones_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Statuses_url string `json:"statuses_url"` + Downloads_url string `json:"downloads_url"` + Releases_url string `json:"releases_url"` + Description string `json:"description"` + Id int64 `json:"id"` // Unique identifier of the repository + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Merges_url string `json:"merges_url"` + Git_tags_url string `json:"git_tags_url"` + Events_url string `json:"events_url"` + Git_url string `json:"git_url"` + Forks int `json:"forks"` + Hooks_url string `json:"hooks_url"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Owner GeneratedType `json:"owner"` // A GitHub user. + Issue_events_url string `json:"issue_events_url"` + Issues_url string `json:"issues_url"` + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + License GeneratedType `json:"license"` // License Simple + Full_name string `json:"full_name"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Blobs_url string `json:"blobs_url"` + Created_at string `json:"created_at"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Has_pages bool `json:"has_pages"` + Watchers int `json:"watchers"` + Branches_url string `json:"branches_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Pushed_at string `json:"pushed_at"` + Pulls_url string `json:"pulls_url"` + Fork bool `json:"fork"` + Comments_url string `json:"comments_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). + 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. + Open_issues_count int `json:"open_issues_count"` +} + +// Webhookscomment represents the Webhookscomment schema from the OpenAPI specification +type Webhookscomment struct { + Id int `json:"id"` + Updated_at string `json:"updated_at"` + User map[string]interface{} `json:"user"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Body string `json:"body"` + Html_url string `json:"html_url"` + Parent_id int `json:"parent_id"` + Repository_url string `json:"repository_url"` + Child_comment_count int `json:"child_comment_count"` + Discussion_id int `json:"discussion_id"` + Node_id string `json:"node_id"` + Reactions map[string]interface{} `json:"reactions"` + Created_at string `json:"created_at"` +} + +// Webhooksuser represents the Webhooksuser schema from the OpenAPI specification +type Webhooksuser struct { + Repos_url string `json:"repos_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + Url string `json:"url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Node_id string `json:"node_id,omitempty"` + TypeField string `json:"type,omitempty"` + Followers_url string `json:"followers_url,omitempty"` + Gists_url string `json:"gists_url,omitempty"` + Events_url string `json:"events_url,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Name string `json:"name,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + Id int64 `json:"id"` + Avatar_url string `json:"avatar_url,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Login string `json:"login"` + Deleted bool `json:"deleted,omitempty"` + Email string `json:"email,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)." + Requestor Webhooksuser `json:"requestor"` + Sender GeneratedType `json:"sender"` // A GitHub user. + Environment string `json:"environment"` + Workflow_job_run map[string]interface{} `json:"workflow_job_run"` + Workflow_run map[string]interface{} `json:"workflow_run"` + 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. + Since string `json:"since"` + 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)." + Reviewers []map[string]interface{} `json:"reviewers"` +} + +// 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 { + 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_refs_url string `json:"git_refs_url"` + Languages_url string `json:"languages_url"` + Default_branch string `json:"default_branch"` + Issue_comment_url string `json:"issue_comment_url"` + Trees_url string `json:"trees_url"` + 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. + Commits_url string `json:"commits_url"` + Has_discussions bool `json:"has_discussions"` + Url string `json:"url"` + Issue_events_url string `json:"issue_events_url"` + Has_issues bool `json:"has_issues"` + Collaborators_url string `json:"collaborators_url"` + Git_url string `json:"git_url"` + Teams_url string `json:"teams_url"` + Is_template bool `json:"is_template,omitempty"` + Events_url string `json:"events_url"` + Parent Repository `json:"parent,omitempty"` // A repository on GitHub. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub user. + Stargazers_url string `json:"stargazers_url"` + Git_tags_url string `json:"git_tags_url"` + Compare_url string `json:"compare_url"` + Subscribers_count int `json:"subscribers_count"` + Comments_url string `json:"comments_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Assignees_url string `json:"assignees_url"` + Mirror_url string `json:"mirror_url"` + Watchers int `json:"watchers"` + Stargazers_count int `json:"stargazers_count"` + Security_and_analysis GeneratedType `json:"security_and_analysis,omitempty"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Created_at string `json:"created_at"` + Archived bool `json:"archived"` + Git_commits_url string `json:"git_commits_url"` + Branches_url string `json:"branches_url"` + Description string `json:"description"` + Statuses_url string `json:"statuses_url"` + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` + Contents_url string `json:"contents_url"` + Has_wiki bool `json:"has_wiki"` + Fork bool `json:"fork"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Forks int `json:"forks"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Id int64 `json:"id"` + Allow_forking bool `json:"allow_forking,omitempty"` + Name string `json:"name"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Notifications_url string `json:"notifications_url"` + Open_issues int `json:"open_issues"` + Pulls_url string `json:"pulls_url"` + Clone_url string `json:"clone_url"` + Milestones_url string `json:"milestones_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. + Pushed_at string `json:"pushed_at"` + 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. + Releases_url string `json:"releases_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Homepage string `json:"homepage"` + Topics []string `json:"topics,omitempty"` + Svn_url string `json:"svn_url"` + Has_pages bool `json:"has_pages"` + Language string `json:"language"` + Master_branch string `json:"master_branch,omitempty"` + Forks_url string `json:"forks_url"` + License GeneratedType `json:"license"` // License Simple + Network_count int `json:"network_count"` + Hooks_url string `json:"hooks_url"` + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is allowed. + Subscription_url string `json:"subscription_url"` + Updated_at string `json:"updated_at"` + Private bool `json:"private"` + Downloads_url string `json:"downloads_url"` + Forks_count int `json:"forks_count"` + Issues_url string `json:"issues_url"` + Template_repository GeneratedType `json:"template_repository,omitempty"` // A repository on GitHub. + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` + Allow_update_branch bool `json:"allow_update_branch,omitempty"` + Tags_url string `json:"tags_url"` + Node_id string `json:"node_id"` + Use_squash_pr_title_as_default bool `json:"use_squash_pr_title_as_default,omitempty"` + Keys_url string `json:"keys_url"` + Labels_url string `json:"labels_url"` + Ssh_url string `json:"ssh_url"` + Deployments_url string `json:"deployments_url"` + Full_name string `json:"full_name"` + 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). + Html_url string `json:"html_url"` + Subscribers_url string `json:"subscribers_url"` + Has_downloads bool `json:"has_downloads,omitempty"` + Watchers_count int `json:"watchers_count"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Source Repository `json:"source,omitempty"` // A repository on GitHub. + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` + Merges_url string `json:"merges_url"` + Archive_url string `json:"archive_url"` + Contributors_url string `json:"contributors_url"` + Has_projects bool `json:"has_projects"` + Open_issues_count int `json:"open_issues_count"` + Blobs_url string `json:"blobs_url"` + Code_of_conduct GeneratedType `json:"code_of_conduct,omitempty"` // Code of Conduct Simple +} + +// 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 { + 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Required_linear_history map[string]interface{} `json:"required_linear_history,omitempty"` + Required_signatures map[string]interface{} `json:"required_signatures,omitempty"` + Restrictions GeneratedType `json:"restrictions,omitempty"` // Branch Restriction Policy + Url string `json:"url"` + 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_status_checks GeneratedType `json:"required_status_checks,omitempty"` // Status Check Policy + Allow_force_pushes map[string]interface{} `json:"allow_force_pushes,omitempty"` + Block_creations map[string]interface{} `json:"block_creations,omitempty"` + Required_pull_request_reviews map[string]interface{} `json:"required_pull_request_reviews,omitempty"` + Allow_deletions map[string]interface{} `json:"allow_deletions,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. + Enforce_admins map[string]interface{} `json:"enforce_admins,omitempty"` + Required_conversation_resolution map[string]interface{} `json:"required_conversation_resolution,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. + 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)." + Previous_marketplace_purchase map[string]interface{} `json:"previous_marketplace_purchase,omitempty"` + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + 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 { + 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 { + 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. + Color string `json:"color,omitempty"` // Color for the issue type. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Week int `json:"week"` + Days []int `json:"days"` + Total int `json:"total"` +} + +// 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 { + 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. + Closed_at string `json:"closed_at"` // The date and time of when the advisory was closed, in ISO 8601 format. + Cwe_ids []string `json:"cwe_ids"` // A list of only the CWE IDs. + Ghsa_id string `json:"ghsa_id"` // The GitHub Security Advisory ID. + Url string `json:"url"` // The API URL for the advisory. + Withdrawn_at string `json:"withdrawn_at"` // The date and time of when the advisory was withdrawn, in ISO 8601 format. + Collaborating_users []GeneratedType `json:"collaborating_users"` // A list of users that collaborate on the advisory. + Identifiers []map[string]interface{} `json:"identifiers"` + Created_at string `json:"created_at"` // The date and time of when the advisory was created, in ISO 8601 format. + Credits []map[string]interface{} `json:"credits"` + State string `json:"state"` // The state of the advisory. + Summary string `json:"summary"` // A short summary of the advisory. + Private_fork interface{} `json:"private_fork"` // A temporary private fork of the advisory's repository for collaborating on a fix. + Cvss_severities GeneratedType `json:"cvss_severities,omitempty"` + Publisher interface{} `json:"publisher"` // The publisher of the advisory. + Author interface{} `json:"author"` // The author of the advisory. + 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. + Description string `json:"description"` // A detailed description of what the advisory entails. + Published_at string `json:"published_at"` // The date and time of when the advisory was published, in ISO 8601 format. + Submission map[string]interface{} `json:"submission"` + Severity string `json:"severity"` // The severity of the advisory. + Vulnerabilities []GeneratedType `json:"vulnerabilities"` + Cvss map[string]interface{} `json:"cvss"` + Cwes []map[string]interface{} `json:"cwes"` + Credits_detailed []GeneratedType `json:"credits_detailed"` +} + +// 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 { + 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)." + 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"` // 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)." +} + +// 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. + Action string `json:"action"` + Assignee Webhooksusermannequin `json:"assignee,omitempty"` + Number int `json:"number"` // The pull request number. + Sender GeneratedType `json:"sender,omitempty"` // 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"` // 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 map[string]interface{} `json:"pull_request"` +} + +// 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,omitempty"` // A GitHub user. + Action string `json:"action"` + Alert GeneratedType `json:"alert"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repository_property map[string]interface{} `json:"repository_property"` +} + +// 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 { + 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 + Message string `json:"message"` // Message describing the purpose of the commit + Timestamp string `json:"timestamp"` // Timestamp of the commit +} + +// 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)." + Forkee interface{} `json:"forkee"` // The created [`repository`](https://docs.github.com/rest/repos/repos#get-a-repository) 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)." + 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 { + Push_protection_bypassed bool `json:"push_protection_bypassed,omitempty"` // Whether push protection was bypassed for the detected secret. + Url string `json:"url,omitempty"` // The REST API URL of the alert resource. + Push_protection_bypass_request_reviewer_comment string `json:"push_protection_bypass_request_reviewer_comment,omitempty"` // An optional comment when reviewing a push protection bypass. + Repository GeneratedType `json:"repository,omitempty"` // A GitHub repository. + Resolution_comment string `json:"resolution_comment,omitempty"` // The comment that was optionally added when this alert was closed + Multi_repo bool `json:"multi_repo,omitempty"` // Whether the detected secret was found in multiple repositories in the same organization or enterprise. + 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_at string `json:"resolved_at,omitempty"` // The time that the alert was resolved 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. + Number int `json:"number,omitempty"` // The security alert number. + State string `json:"state,omitempty"` // Sets the state of the secret scanning alert. You must provide `resolution` when you set the state to `resolved`. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Resolution string `json:"resolution,omitempty"` // **Required when the `state` is `resolved`.** The reason for resolving the alert. + Validity string `json:"validity,omitempty"` // The token status as of the latest validity check. + Push_protection_bypass_request_comment string `json:"push_protection_bypass_request_comment,omitempty"` // An optional comment when requesting a push protection bypass. + 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. + Resolved_by GeneratedType `json:"resolved_by,omitempty"` // A GitHub user. + Html_url string `json:"html_url,omitempty"` // The GitHub URL of the alert resource. + Push_protection_bypass_request_reviewer GeneratedType `json:"push_protection_bypass_request_reviewer,omitempty"` // A GitHub user. + Secret string `json:"secret,omitempty"` // The secret that was detected. + Publicly_leaked bool `json:"publicly_leaked,omitempty"` // Whether the secret was publicly leaked. + 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_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)." + Created_at string `json:"created_at,omitempty"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Secret_type string `json:"secret_type,omitempty"` // The type of secret that secret scanning detected. + Is_base64_encoded bool `json:"is_base64_encoded,omitempty"` // A boolean value representing whether or not alert is base64 encoded + Locations_url string `json:"locations_url,omitempty"` // The REST API URL of the code locations for this alert. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Views []Traffic `json:"views"` + Count int `json:"count"` + Uniques int `json:"uniques"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Pull_request map[string]interface{} `json:"pull_request"` + 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"` + Reason string `json:"reason"` + 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,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"` + 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 { + Html_url string `json:"html_url"` + Id int `json:"id"` + Login string `json:"login"` + Name string `json:"name"` + Node_id string `json:"node_id"` + Avatar_url string `json:"avatar_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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. + Assigning_team interface{} `json:"assigning_team,omitempty"` // The team through which the assignee is granted access to GitHub Copilot, if applicable. + Created_at string `json:"created_at"` // Timestamp of when the assignee was last granted access to GitHub Copilot, in ISO 8601 format. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub organization. + Plan_type string `json:"plan_type,omitempty"` // The Copilot plan of the organization, or the parent enterprise, when applicable. + Assignee GeneratedType `json:"assignee,omitempty"` // A GitHub user. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Events []string `json:"events"` + Updated_at string `json:"updated_at"` + Id int `json:"id"` + Ping_url string `json:"ping_url"` + TypeField string `json:"type"` + Active bool `json:"active"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Deliveries_url string `json:"deliveries_url,omitempty"` + Name string `json:"name"` + Config map[string]interface{} `json:"config"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Property_name string `json:"property_name"` // The name of the property + Value string `json:"value"` // The value assigned to the property +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Metadata map[string]interface{} `json:"metadata,omitempty"` + Status string `json:"status,omitempty"` + Documentation_url string `json:"documentation_url,omitempty"` + Message string `json:"message,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Event string `json:"event"` + Id int `json:"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. + Assigner GeneratedType `json:"assigner"` // A GitHub user. + Commit_id string `json:"commit_id"` + Node_id string `json:"node_id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Url string `json:"url"` + Commit_url string `json:"commit_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the hosted runner. + Platform string `json:"platform"` // The operating system of the image. + Public_ip_enabled bool `json:"public_ip_enabled"` // Whether public IP is enabled for the hosted runners. + Public_ips []GeneratedType `json:"public_ips,omitempty"` // The public IP ranges when public IP is enabled for the hosted runners. + Image_details GeneratedType `json:"image_details"` // Provides details of a hosted runner image + Status string `json:"status"` // The status of the runner. + Last_active_on string `json:"last_active_on,omitempty"` // The time at which the runner was last used, in ISO 8601 format. + 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. + Id int `json:"id"` // The unique identifier of the hosted runner. + Runner_group_id int `json:"runner_group_id,omitempty"` // The unique identifier of the group that the hosted runner belongs to. + Machine_size_details GeneratedType `json:"machine_size_details"` // Provides details of a particular machine spec. +} + +// 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 { + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// 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 { + 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`. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Message string `json:"message,omitempty"` // Commit message to be used. +} + +// 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"` + Changes map[string]interface{} `json:"changes"` +} + +// 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_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)." + 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. + 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)." +} + +// 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 { + Sha string `json:"sha"` + Size int `json:"size"` + Content string `json:"content,omitempty"` + Encoding string `json:"encoding,omitempty"` + Download_url string `json:"download_url"` + Entries []map[string]interface{} `json:"entries,omitempty"` + Html_url string `json:"html_url"` + Name string `json:"name"` + Links map[string]interface{} `json:"_links"` + TypeField string `json:"type"` + Url string `json:"url"` + Git_url string `json:"git_url"` + Path string `json:"path"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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`. + Summary string `json:"summary"` // A short summary of the advisory. + Start_private_fork bool `json:"start_private_fork,omitempty"` // Whether to create a temporary private fork of the repository to collaborate on a fix. + Credits []map[string]interface{} `json:"credits,omitempty"` // A list of users receiving credit for their participation in the security advisory. + 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. + 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`. +} + +// 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 { + Issue map[string]interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) itself. + Changes map[string]interface{} `json:"changes"` // The changes to the 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)." + 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. + 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. + 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)." + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Event string `json:"event"` + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + 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. + Milestone map[string]interface{} `json:"milestone"` + Url string `json:"url"` + Commit_id string `json:"commit_id"` +} + +// Codespace represents the Codespace schema from the OpenAPI specification +type Codespace struct { + Pulls_url string `json:"pulls_url"` // API URL for the Pull Request associated with this codespace, if any. + Devcontainer_path string `json:"devcontainer_path,omitempty"` // Path to devcontainer.json from repo root used to create Codespace. + Id int64 `json:"id"` + Prebuild bool `json:"prebuild"` // Whether the codespace was created from a prebuild. + Web_url string `json:"web_url"` // URL to access this codespace on the web. + Stop_url string `json:"stop_url"` // API URL to stop this codespace. + Runtime_constraints map[string]interface{} `json:"runtime_constraints,omitempty"` + Name string `json:"name"` // Automatically generated name of this codespace. + Recent_folders []string `json:"recent_folders"` + 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. + Url string `json:"url"` // API URL for this codespace. + 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). + Machine GeneratedType `json:"machine"` // A description of the machine powering a codespace. + Owner GeneratedType `json:"owner"` // A GitHub user. + Publish_url string `json:"publish_url,omitempty"` // API URL to publish this codespace to a new repository. + Repository GeneratedType `json:"repository"` // Minimal Repository + 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. + Start_url string `json:"start_url"` // API URL to start this codespace. + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Last_used_at string `json:"last_used_at"` // Last known time this codespace was started. + State string `json:"state"` // State of this codespace. + Display_name string `json:"display_name,omitempty"` // Display name 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. + Machines_url string `json:"machines_url"` // API URL to access available alternate machine types for this codespace. + 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_disabled_reason string `json:"pending_operation_disabled_reason,omitempty"` // Text to show user when codespace is disabled by a pending operation + Billable_owner GeneratedType `json:"billable_owner"` // A GitHub user. + Environment_id string `json:"environment_id"` // UUID identifying this codespace's environment. + Location string `json:"location"` // The initally assigned location of a new codespace. + Git_status map[string]interface{} `json:"git_status"` // Details about the codespace's git repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Compare_url string `json:"compare_url"` // A template for the API URL to compare two commits or refs. + Labels_url string `json:"labels_url"` // A template for the API URL to get information about labels of the repository. + Forks_url string `json:"forks_url"` // The API URL to list the forks 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. + Stargazers_url string `json:"stargazers_url"` // The API URL to list the stargazers on the repository. + Subscribers_url string `json:"subscribers_url"` // The API URL to list the subscribers on the repository. + Issues_url string `json:"issues_url"` // A template for the API URL to get information about issues on the repository. + Releases_url string `json:"releases_url"` // A template for the API URL to get information about releases on 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. + 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. + Id int64 `json:"id"` // A unique identifier of the repository. + Milestones_url string `json:"milestones_url"` // A template for the API URL to get information about milestones 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. + Contributors_url string `json:"contributors_url"` // A template for the API URL to list the contributors to the repository. + Keys_url string `json:"keys_url"` // A template for the API URL to get information about deploy keys on the repository. + Subscription_url string `json:"subscription_url"` // The API URL to subscribe to notifications for this repository. + Languages_url string `json:"languages_url"` // The API URL to get information about the languages of the repository. + Description string `json:"description"` // The repository description. + Issue_comment_url string `json:"issue_comment_url"` // A template for the API URL to get information about issue comments 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. + Teams_url string `json:"teams_url"` // The API URL to list the teams on the repository. + Comments_url string `json:"comments_url"` // A template for the API URL to get information about comments on the repository. + Commits_url string `json:"commits_url"` // A template for the API URL to get information about commits on the repository. + Branches_url string `json:"branches_url"` // A template for the API URL to get information about branches in the repository. + Tags_url string `json:"tags_url"` // The API URL to get information about tags on the repository. + Deployments_url string `json:"deployments_url"` // The API URL to list the deployments of the repository. + Fork bool `json:"fork"` // Whether the repository is a fork. + Html_url string `json:"html_url"` // The URL to view the repository on GitHub.com. + Collaborators_url string `json:"collaborators_url"` // A template for the API URL to get information about collaborators of the repository. + Statuses_url string `json:"statuses_url"` // A template for the API URL to get information about statuses of a commit. + Hooks_url string `json:"hooks_url"` // The API URL to list the hooks on the repository. + Owner GeneratedType `json:"owner"` // A GitHub user. + Trees_url string `json:"trees_url"` // A template for the API URL to create or retrieve a raw Git tree of the repository. + Contents_url string `json:"contents_url"` // A template for the API URL to get the contents of the repository. + Full_name string `json:"full_name"` // The full, globally unique, name of the repository. + Name string `json:"name"` // The name of the repository. + Merges_url string `json:"merges_url"` // The API URL to merge branches in the repository. + Private bool `json:"private"` // Whether the repository is private. + Pulls_url string `json:"pulls_url"` // A template for the API URL to get information about pull requests on the repository. + Url string `json:"url"` // The URL to get more information about the repository from the GitHub API. + Archive_url string `json:"archive_url"` // A template for the API URL to download the repository as an archive. + Git_tags_url string `json:"git_tags_url"` // A template for the API URL to get information about Git tags of the repository. + Node_id string `json:"node_id"` // The GraphQL identifier of 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + After string `json:"after,omitempty"` + Created_at string `json:"created_at,omitempty"` + Head_sha string `json:"head_sha,omitempty"` // The SHA of the head commit that is being checked. + Id int `json:"id,omitempty"` + Repository GeneratedType `json:"repository,omitempty"` // Minimal Repository + Status string `json:"status,omitempty"` + Before string `json:"before,omitempty"` + Head_branch string `json:"head_branch,omitempty"` + Url string `json:"url,omitempty"` + Conclusion string `json:"conclusion,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. + Node_id string `json:"node_id,omitempty"` + Pull_requests []GeneratedType `json:"pull_requests,omitempty"` + Updated_at string `json:"updated_at,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 { + 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 + Repositories_url string `json:"repositories_url"` + Slug string `json:"slug"` + Description string `json:"description"` // Description of the team + Node_id string `json:"node_id"` + Url string `json:"url"` // URL for the team + Notification_setting string `json:"notification_setting,omitempty"` // The notification setting the team has set + Privacy string `json:"privacy,omitempty"` // The level of privacy this team should have + Html_url string `json:"html_url"` + Members_url string `json:"members_url"` + Name string `json:"name"` // Name of the team + Id int `json:"id"` // Unique identifier of the team +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Storage_gb int `json:"storage_gb"` // The available SSD storage for the machine spec. + 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. +} + +// 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 { + Id int `json:"id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Project_card map[string]interface{} `json:"project_card,omitempty"` + Commit_id string `json:"commit_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. + Url string `json:"url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Files map[string]interface{} `json:"files"` + 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"` +} + +// 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 { + Help string `json:"help,omitempty"` // Detailed documentation for the rule as GitHub Flavored Markdown. + Help_uri string `json:"help_uri,omitempty"` // A link to the documentation for the rule used to detect the alert. + Security_severity_level string `json:"security_severity_level,omitempty"` // The security severity of the alert. + Name string `json:"name,omitempty"` // The name of the rule used to detect the alert. + Tags []string `json:"tags,omitempty"` // A set of tags applicable for the rule. + Id string `json:"id,omitempty"` // A unique identifier for the rule used to detect the alert. + Severity string `json:"severity,omitempty"` // The severity of the alert. + Description string `json:"description,omitempty"` // A short description of the rule used to detect the alert. + Full_description string `json:"full_description,omitempty"` // A description of the rule used to detect the alert. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dependency map[string]interface{} `json:"dependency"` // Details for the vulnerable dependency. + Url string `json:"url"` // The REST API URL of the alert resource. + Dismissed_comment string `json:"dismissed_comment"` // An optional comment associated with the alert's dismissal. + Number int `json:"number"` // The security alert number. + Dismissed_reason string `json:"dismissed_reason"` // The reason that the alert was dismissed. + Updated_at string `json:"updated_at"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Security_vulnerability GeneratedType `json:"security_vulnerability"` // Details pertaining to one vulnerable version range for the advisory. + 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`. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Security_advisory GeneratedType `json:"security_advisory"` // Details for the GitHub Security Advisory. + State string `json:"state"` // The state of the Dependabot alert. + 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`. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Repository GeneratedType `json:"repository"` // A GitHub repository. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Hosted_runners_url string `json:"hosted_runners_url,omitempty"` + Inherited bool `json:"inherited"` + Inherited_allows_public_repositories bool `json:"inherited_allows_public_repositories,omitempty"` + Network_configuration_id string `json:"network_configuration_id,omitempty"` // The identifier of a hosted compute network configuration. + 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. + Runners_url string `json:"runners_url"` + Allows_public_repositories bool `json:"allows_public_repositories"` + DefaultField bool `json:"default"` + Id float64 `json:"id"` + Name string `json:"name"` + 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` + 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"` + Workflow_restrictions_read_only bool `json:"workflow_restrictions_read_only,omitempty"` // If `true`, the `restricted_to_workflows` and `selected_workflows` fields cannot be modified. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Id int `json:"id"` + Key string `json:"key"` + Title string `json:"title"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Full_name string `json:"full_name"` // The repository owner and name for the cache usage being shown. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { +} + +// 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 { + 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"` // 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 { + 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 { + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Commit_url string `json:"commit_url"` + 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. + Created_at string `json:"created_at"` + Url string `json:"url"` + Commit_id string `json:"commit_id"` + Node_id string `json:"node_id"` + Actor GeneratedType `json:"actor"` // A GitHub user. +} + +// 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. + 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_id float64 `json:"sub_issue_id"` // The ID of the sub-issue. + Action string `json:"action"` + 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. + Parent_issue_repo Repository `json:"parent_issue_repo"` // A repository on GitHub. +} + +// 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"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. +} + +// 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. + 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. + 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 { + 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. + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit_id string `json:"commit_id,omitempty"` + Event string `json:"event,omitempty"` + Node_id string `json:"node_id,omitempty"` + Comments []GeneratedType `json:"comments,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 GeneratedType `json:"projects_v2"` // A projects v2 project + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + Protected bool `json:"protected"` +} + +// 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"` + Comment map[string]interface{} `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)." + Issue interface{} `json:"issue"` // The [issue](https://docs.github.com/rest/issues/issues#get-an-issue) the comment belongs to. +} + +// 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"` + 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Archived bool `json:"archived,omitempty"` + Created_at string `json:"created_at,omitempty"` + Network_count int `json:"network_count,omitempty"` + Has_downloads bool `json:"has_downloads,omitempty"` + Has_issues bool `json:"has_issues,omitempty"` + Languages_url string `json:"languages_url"` + Code_of_conduct GeneratedType `json:"code_of_conduct,omitempty"` // Code Of Conduct + Svn_url string `json:"svn_url,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. + Git_tags_url string `json:"git_tags_url"` + Topics []string `json:"topics,omitempty"` + Forks_url string `json:"forks_url"` + Default_branch string `json:"default_branch,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. + Commits_url string `json:"commits_url"` + Has_pages bool `json:"has_pages,omitempty"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Id int64 `json:"id"` + Assignees_url string `json:"assignees_url"` + Tags_url string `json:"tags_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Events_url string `json:"events_url"` + Full_name string `json:"full_name"` + Role_name string `json:"role_name,omitempty"` + Branches_url string `json:"branches_url"` + Notifications_url string `json:"notifications_url"` + Has_discussions bool `json:"has_discussions,omitempty"` + Labels_url string `json:"labels_url"` + Updated_at string `json:"updated_at,omitempty"` + Homepage string `json:"homepage,omitempty"` + Allow_forking bool `json:"allow_forking,omitempty"` + Clone_url string `json:"clone_url,omitempty"` + Git_refs_url string `json:"git_refs_url"` + Security_and_analysis GeneratedType `json:"security_and_analysis,omitempty"` + Open_issues_count int `json:"open_issues_count,omitempty"` + Releases_url string `json:"releases_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Git_commits_url string `json:"git_commits_url"` + Trees_url string `json:"trees_url"` + Contributors_url string `json:"contributors_url"` + Watchers int `json:"watchers,omitempty"` + Ssh_url string `json:"ssh_url,omitempty"` + Description string `json:"description"` + Subscribers_url string `json:"subscribers_url"` + Teams_url string `json:"teams_url"` + Node_id string `json:"node_id"` + Private bool `json:"private"` + Watchers_count int `json:"watchers_count,omitempty"` + Name string `json:"name"` + Mirror_url string `json:"mirror_url,omitempty"` + Open_issues int `json:"open_issues,omitempty"` + Collaborators_url string `json:"collaborators_url"` + Subscription_url string `json:"subscription_url"` + Stargazers_count int `json:"stargazers_count,omitempty"` + Contents_url string `json:"contents_url"` + Downloads_url string `json:"downloads_url"` + Forks_count int `json:"forks_count,omitempty"` + Has_projects bool `json:"has_projects,omitempty"` + Keys_url string `json:"keys_url"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Html_url string `json:"html_url"` + Statuses_url string `json:"statuses_url"` + Compare_url string `json:"compare_url"` + Has_wiki bool `json:"has_wiki,omitempty"` + Deployments_url string `json:"deployments_url"` + Forks int `json:"forks,omitempty"` + Url string `json:"url"` + Pulls_url string `json:"pulls_url"` + Hooks_url string `json:"hooks_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Issues_url string `json:"issues_url"` + Fork bool `json:"fork"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Comments_url string `json:"comments_url"` + Language string `json:"language,omitempty"` + Git_url string `json:"git_url,omitempty"` + Pushed_at string `json:"pushed_at,omitempty"` + Blobs_url string `json:"blobs_url"` + Stargazers_url string `json:"stargazers_url"` + Visibility string `json:"visibility,omitempty"` + Disabled bool `json:"disabled,omitempty"` + Is_template bool `json:"is_template,omitempty"` + Issue_comment_url string `json:"issue_comment_url"` + License map[string]interface{} `json:"license,omitempty"` + Milestones_url string `json:"milestones_url"` + Merges_url string `json:"merges_url"` + Archive_url string `json:"archive_url"` + Issue_events_url string `json:"issue_events_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + Bypass_pull_request_allowances map[string]interface{} `json:"bypass_pull_request_allowances,omitempty"` // Allow specific users, teams, or apps to bypass pull request requirements. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + 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. + 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. + 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 { + 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. +} + +// Webhooksrelease represents the Webhooksrelease schema from the OpenAPI specification +type Webhooksrelease struct { + Created_at string `json:"created_at"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + Prerelease bool `json:"prerelease"` // Whether the release is identified as a prerelease or a full release. + Tarball_url string `json:"tarball_url"` + Discussion_url string `json:"discussion_url,omitempty"` + Target_commitish string `json:"target_commitish"` // Specifies the commitish value that determines where the Git tag is created from. + Upload_url string `json:"upload_url"` + Node_id string `json:"node_id"` + Author map[string]interface{} `json:"author"` + Url string `json:"url"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Name string `json:"name"` + Tag_name string `json:"tag_name"` // The name of the tag. + Zipball_url string `json:"zipball_url"` + Assets []map[string]interface{} `json:"assets"` + Published_at string `json:"published_at"` + Assets_url string `json:"assets_url"` + Body string `json:"body"` + Draft bool `json:"draft"` // Whether the release is a draft or published +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int64 `json:"id"` // Unique identifier of the repository + Contents_url string `json:"contents_url"` + Url string `json:"url"` + 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. + Open_issues int `json:"open_issues"` + Template_repository map[string]interface{} `json:"template_repository,omitempty"` + Hooks_url string `json:"hooks_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` // Whether to require contributors to sign off on web-based commits + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Trees_url string `json:"trees_url"` + Comments_url string `json:"comments_url"` + Starred_at string `json:"starred_at,omitempty"` + Contributors_url string `json:"contributors_url"` + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Updated_at string `json:"updated_at"` + Mirror_url string `json:"mirror_url"` + Pulls_url string `json:"pulls_url"` + Forks_count int `json:"forks_count"` + Stargazers_url string `json:"stargazers_url"` + Has_pages bool `json:"has_pages"` + Fork bool `json:"fork"` + Commits_url string `json:"commits_url"` + Topics []string `json:"topics,omitempty"` + Compare_url string `json:"compare_url"` + Assignees_url string `json:"assignees_url"` + Blobs_url string `json:"blobs_url"` + 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. + Deployments_url string `json:"deployments_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). + Forks int `json:"forks"` + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Releases_url string `json:"releases_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). + Tags_url string `json:"tags_url"` + Labels_url string `json:"labels_url"` + Archived bool `json:"archived"` // Whether the repository is archived. + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + Subscription_url string `json:"subscription_url"` + License GeneratedType `json:"license"` // License Simple + Node_id string `json:"node_id"` + Watchers_count int `json:"watchers_count"` + Archive_url string `json:"archive_url"` + Full_name string `json:"full_name"` + Forks_url string `json:"forks_url"` + Issues_url string `json:"issues_url"` + Homepage string `json:"homepage"` + Master_branch string `json:"master_branch,omitempty"` + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Issue_comment_url string `json:"issue_comment_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. + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Watchers int `json:"watchers"` + Clone_url string `json:"clone_url"` + Network_count int `json:"network_count,omitempty"` + Stargazers_count int `json:"stargazers_count"` + Private bool `json:"private"` // Whether the repository is private or public. + Organization GeneratedType `json:"organization,omitempty"` // A GitHub user. + Teams_url string `json:"teams_url"` + Name string `json:"name"` // The name of the repository. + Collaborators_url string `json:"collaborators_url"` + Git_commits_url string `json:"git_commits_url"` + Git_tags_url string `json:"git_tags_url"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Languages_url string `json:"languages_url"` + Pushed_at string `json:"pushed_at"` + Default_branch string `json:"default_branch"` // The default branch of the repository. + 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. + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Created_at string `json:"created_at"` + 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. + 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_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Merges_url string `json:"merges_url"` + Keys_url string `json:"keys_url"` + Statuses_url string `json:"statuses_url"` + Git_refs_url string `json:"git_refs_url"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` // Whether to delete head branches when pull requests are merged + Issue_events_url string `json:"issue_events_url"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Svn_url string `json:"svn_url"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Notifications_url string `json:"notifications_url"` + Html_url string `json:"html_url"` + Downloads_url string `json:"downloads_url"` + Events_url string `json:"events_url"` + Milestones_url string `json:"milestones_url"` + Subscribers_url string `json:"subscribers_url"` + Git_url string `json:"git_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. + Description string `json:"description"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + Open_issues_count int `json:"open_issues_count"` + Ssh_url string `json:"ssh_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Language string `json:"language"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dependabot []string `json:"dependabot,omitempty"` + Importer []string `json:"importer,omitempty"` + Ssh_keys []string `json:"ssh_keys,omitempty"` + Github_enterprise_importer []string `json:"github_enterprise_importer,omitempty"` + Web []string `json:"web,omitempty"` + Actions_macos []string `json:"actions_macos,omitempty"` + Domains map[string]interface{} `json:"domains,omitempty"` + Actions []string `json:"actions,omitempty"` + Ssh_key_fingerprints map[string]interface{} `json:"ssh_key_fingerprints,omitempty"` + Api []string `json:"api,omitempty"` + Codespaces []string `json:"codespaces,omitempty"` + Copilot []string `json:"copilot,omitempty"` + Packages []string `json:"packages,omitempty"` + Pages []string `json:"pages,omitempty"` + Git []string `json:"git,omitempty"` + Hooks []string `json:"hooks,omitempty"` + Verifiable_password_authentication bool `json:"verifiable_password_authentication"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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_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 { + Roster_identifier string `json:"roster_identifier"` // Roster identifier of the student + Assignment_name string `json:"assignment_name"` // Name 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 + Points_awarded int `json:"points_awarded"` // Number of points awarded to the student + Starter_code_url string `json:"starter_code_url"` // URL of the starter code for the assignment + Student_repository_url string `json:"student_repository_url"` // URL of the student's assignment repository + Submission_timestamp string `json:"submission_timestamp"` // Timestamp of the student's assignment submission + Assignment_url string `json:"assignment_url"` // URL of the assignment + Points_available int `json:"points_available"` // Number of points available for the assignment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Size int `json:"size"` + Encoding string `json:"encoding"` + Target string `json:"target,omitempty"` + Url string `json:"url"` + Git_url string `json:"git_url"` + Path string `json:"path"` + Sha string `json:"sha"` + Content string `json:"content"` + Submodule_git_url string `json:"submodule_git_url,omitempty"` + TypeField string `json:"type"` + Links map[string]interface{} `json:"_links"` + Download_url string `json:"download_url"` + Html_url string `json:"html_url"` + Name string `json:"name"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + 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"` + Id int `json:"id"` // Unique identifier of the deployment + Task string `json:"task"` // Parameter to specify a task to execute + 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. + Node_id string `json:"node_id"` + 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"` + Updated_at string `json:"updated_at"` + Description string `json:"description"` + Environment string `json:"environment"` // Name for the target deployment environment. + Original_environment string `json:"original_environment,omitempty"` + Url string `json:"url"` +} + +// 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. +} + +// 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)." + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Minutes_used_breakdown map[string]interface{} `json:"minutes_used_breakdown"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + 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 { + Ldap_dn string `json:"ldap_dn,omitempty"` // Distinguished Name (DN) that team maps to within LDAP environment + Node_id string `json:"node_id"` + Description string `json:"description"` + Members_url string `json:"members_url"` + Parent GeneratedType `json:"parent,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Created_at string `json:"created_at"` + Id int `json:"id"` // Unique identifier of the team + Name string `json:"name"` // Name of the team + Permission string `json:"permission"` // Permission that the team will have for its repositories + Privacy string `json:"privacy,omitempty"` // The level of privacy this team should have + Organization GeneratedType `json:"organization"` // Team Organization + Slug string `json:"slug"` + Html_url string `json:"html_url"` + Notification_setting string `json:"notification_setting,omitempty"` // The notification setting the team has set + Repos_count int `json:"repos_count"` + Repositories_url string `json:"repositories_url"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` // URL for the team + Members_count int `json:"members_count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// 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. +} + +// Webhooksissuecomment represents the Webhooksissuecomment schema from the OpenAPI specification +type Webhooksissuecomment struct { + Id int64 `json:"id"` // Unique identifier of the issue comment + 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. + Node_id string `json:"node_id"` + Reactions map[string]interface{} `json:"reactions"` + Body string `json:"body"` // Contents of the issue comment + Created_at string `json:"created_at"` + Issue_url string `json:"issue_url"` + Updated_at string `json:"updated_at"` + User map[string]interface{} `json:"user"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Html_url string `json:"html_url"` + Url string `json:"url"` // URL for the issue comment +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Previous_marketplace_purchase Webhookspreviousmarketplacepurchase `json:"previous_marketplace_purchase,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)." + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + 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"` + 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. + 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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_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. + 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. + 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_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. + Created_at string `json:"created_at"` // Date and time when the request for access was created. + 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. + Permissions map[string]interface{} `json:"permissions"` // Permissions requested, categorized by type of permission. + Token_expires_at string `json:"token_expires_at"` // Date and time when the associated fine-grained personal access token expires. + Owner GeneratedType `json:"owner"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + 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 { + Id int64 `json:"id"` // Unique identifier of the webhook delivery. + Installation_id int64 `json:"installation_id"` // The id of the GitHub App installation associated with this event. + Status string `json:"status"` // Describes the response returned after attempting 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 webhook delivery occurred. + Redelivery bool `json:"redelivery"` // Whether the webhook delivery is a redelivery. + Status_code int `json:"status_code"` // Status code received when delivery was made. + Event string `json:"event"` // The event that triggered the delivery. + Guid string `json:"guid"` // Unique identifier for the event (shared with all deliveries for all webhooks that subscribe to this event). + Repository_id int64 `json:"repository_id"` // The id of the repository associated with this event. + Throttled_at string `json:"throttled_at,omitempty"` // Time when the webhook delivery was throttled. + Duration float64 `json:"duration"` // Time spent delivering. +} + +// 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)." + Workflow_job_runs []map[string]interface{} `json:"workflow_job_runs,omitempty"` + Workflow_job_run Webhooksworkflowjobrun `json:"workflow_job_run,omitempty"` + Comment string `json:"comment,omitempty"` + 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. + Reviewers []map[string]interface{} `json:"reviewers,omitempty"` + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. + Since string `json:"since"` + Approver Webhooksapprover `json:"approver,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Id int `json:"id"` + Login string `json:"login"` + Avatar_url string `json:"avatar_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"` // 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 { + 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_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_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. + 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. + Token_expires_at string `json:"token_expires_at"` // Date and time when the associated fine-grained personal access token expires. + 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. + Owner GeneratedType `json:"owner"` // A GitHub user. + Permissions_result map[string]interface{} `json:"permissions_result"` // Permissions requested, categorized by type of permission. This field incorporates `permissions_added` and `permissions_upgraded`. + 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`. + Repository_selection string `json:"repository_selection"` // Type of repository selection requested. + Created_at string `json:"created_at"` // Date and time when the request for access was created. + Permissions_added map[string]interface{} `json:"permissions_added"` // New requested permissions, categorized by type of permission. + 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`. + Token_expired bool `json:"token_expired"` // Whether the associated fine-grained personal access token has expired. +} + +// Webhooksapprover represents the Webhooksapprover schema from the OpenAPI specification +type Webhooksapprover struct { + Id int `json:"id,omitempty"` + Events_url string `json:"events_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Login string `json:"login,omitempty"` + Gists_url string `json:"gists_url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + TypeField string `json:"type,omitempty"` + Followers_url string `json:"followers_url,omitempty"` + Repos_url string `json:"repos_url,omitempty"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + Html_url string `json:"html_url,omitempty"` + Received_events_url string `json:"received_events_url,omitempty"` + Url string `json:"url,omitempty"` + Node_id string `json:"node_id,omitempty"` +} + +// Classroom represents the Classroom schema from the OpenAPI specification +type Classroom struct { + Id int `json:"id"` // Unique identifier of the classroom. + Name string `json:"name"` // The name of the classroom. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Id int `json:"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. + Event string `json:"event"` + Node_id string `json:"node_id"` + Commit_id string `json:"commit_id"` + Commit_url string `json:"commit_url"` + Rename map[string]interface{} `json:"rename"` + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. +} + +// 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 { + 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"` + 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 { + 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 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Starred_url string `json:"starred_url"` + Node_id string `json:"node_id"` + Organizations_url string `json:"organizations_url"` + User_view_type string `json:"user_view_type,omitempty"` + Email string `json:"email,omitempty"` + Received_events_url string `json:"received_events_url"` + TypeField string `json:"type"` + Role_name string `json:"role_name"` + Avatar_url string `json:"avatar_url"` + Following_url string `json:"following_url"` + Events_url string `json:"events_url"` + Name string `json:"name,omitempty"` + Gists_url string `json:"gists_url"` + Repos_url string `json:"repos_url"` + Url string `json:"url"` + Id int64 `json:"id"` + Login string `json:"login"` + Subscriptions_url string `json:"subscriptions_url"` + Gravatar_id string `json:"gravatar_id"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Site_admin bool `json:"site_admin"` + Followers_url string `json:"followers_url"` + Html_url string `json:"html_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Strict bool `json:"strict"` + Url string `json:"url"` + Checks []map[string]interface{} `json:"checks"` + Contexts []string `json:"contexts"` + Contexts_url string `json:"contexts_url"` +} + +// 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 { + 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"` + Expires_at string `json:"expires_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Oid string `json:"oid"` + Path string `json:"path"` + Ref_name string `json:"ref_name"` + Size int `json:"size"` +} + +// Webhooksprojectchanges represents the Webhooksprojectchanges schema from the OpenAPI specification +type Webhooksprojectchanges struct { + Archived_at map[string]interface{} `json:"archived_at,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + Start_line float64 `json:"start_line"` // Line number at which the secret starts in the file + Blob_sha string `json:"blob_sha"` // SHA-1 hash ID of the associated blob + Blob_url string `json:"blob_url"` // The API URL to get the associated blob resource + 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 + Commit_sha string `json:"commit_sha"` // SHA-1 hash ID of the associated commit + 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 +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Original_start_line int `json:"original_start_line,omitempty"` // 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. + User GeneratedType `json:"user"` // A GitHub user. + Position int `json:"position,omitempty"` // The line index in the diff to which the comment applies. This field is closing down; use `line` instead. + Pull_request_review_id int64 `json:"pull_request_review_id"` // The ID of the pull request review to which the comment belongs. + Links map[string]interface{} `json:"_links"` + Id int64 `json:"id"` // The ID of the pull request review comment. + Created_at string `json:"created_at"` + Start_line int `json:"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. + 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. + Start_side string `json:"start_side,omitempty"` // The side of the first line of the range for a multi-line comment. + Html_url string `json:"html_url"` // HTML URL for the pull request review comment. + Body_html string `json:"body_html,omitempty"` + 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 + Body_text string `json:"body_text,omitempty"` + Updated_at string `json:"updated_at"` + Diff_hunk string `json:"diff_hunk"` // The diff of the line that the comment refers to. + 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 + 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 + Reactions GeneratedType `json:"reactions,omitempty"` + Original_commit_id string `json:"original_commit_id"` // The SHA of the original commit to which the comment applies. + Pull_request_url string `json:"pull_request_url"` // URL for the pull request that the review comment belongs to. + Node_id string `json:"node_id"` // The node ID of the pull request review comment. + Body string `json:"body"` // The text of the comment. + In_reply_to_id int `json:"in_reply_to_id,omitempty"` // The comment ID to reply to. + Author_association string `json:"author_association"` // How the author is associated with the repository. + Subject_type string `json:"subject_type,omitempty"` // The level at which the comment is targeted, can be a diff line or a file. + 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)." + 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. + 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 { + Issue 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"` // 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Issues_url string `json:"issues_url"` + Node_id string `json:"node_id"` + Events_url string `json:"events_url"` + Id int `json:"id"` + Repos_url string `json:"repos_url"` + Avatar_url string `json:"avatar_url"` + Public_members_url string `json:"public_members_url"` + Url string `json:"url"` + Hooks_url string `json:"hooks_url"` + Login string `json:"login"` + Members_url string `json:"members_url"` + Description string `json:"description"` +} + +// 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"` + Changes map[string]interface{} `json:"changes"` // The changes to the team if the action was `edited`. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Analyses_url string `json:"analyses_url,omitempty"` // The REST API URL for getting the analyses associated with the upload. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Slug string `json:"slug"` // The slugified name of the deployment protection rule integration. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Links map[string]interface{} `json:"_links"` + Git_url string `json:"git_url"` + Sha string `json:"sha"` + Download_url string `json:"download_url"` + Html_url string `json:"html_url"` + Submodule_git_url string `json:"submodule_git_url"` + TypeField string `json:"type"` + Name string `json:"name"` + Path string `json:"path"` + Size int `json:"size"` +} + +// Release represents the Release schema from the OpenAPI specification +type Release struct { + Body_text string `json:"body_text,omitempty"` + Discussion_url string `json:"discussion_url,omitempty"` // The URL of the release discussion. + Draft bool `json:"draft"` // true to create a draft (unpublished) release, false to create a published one. + Mentions_count int `json:"mentions_count,omitempty"` + Html_url string `json:"html_url"` + Assets []GeneratedType `json:"assets"` + Assets_url string `json:"assets_url"` + Tag_name string `json:"tag_name"` // The name of the tag. + Prerelease bool `json:"prerelease"` // Whether to identify the release as a prerelease or a full release. + Tarball_url string `json:"tarball_url"` + Upload_url string `json:"upload_url"` + Url string `json:"url"` + Author GeneratedType `json:"author"` // A GitHub user. + Created_at string `json:"created_at"` + Zipball_url string `json:"zipball_url"` + Id int `json:"id"` + Body string `json:"body,omitempty"` + Node_id string `json:"node_id"` + Name string `json:"name"` + Published_at string `json:"published_at"` + Target_commitish string `json:"target_commitish"` // Specifies the commitish value that determines where the Git tag is created from. + Body_html string `json:"body_html,omitempty"` + Reactions GeneratedType `json:"reactions,omitempty"` +} + +// Package represents the Package schema from the OpenAPI specification +type Package struct { + Url string `json:"url"` + Html_url string `json:"html_url"` + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Owner GeneratedType `json:"owner,omitempty"` // A GitHub user. + Package_type string `json:"package_type"` + Repository GeneratedType `json:"repository,omitempty"` // Minimal Repository + Version_count int `json:"version_count"` // The number of versions of the package. + Visibility string `json:"visibility"` + Id int `json:"id"` // Unique identifier of the package. + Name string `json:"name"` // The name of the package. +} + +// 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 { + TypeField string `json:"type"` + Parameters map[string]interface{} `json:"parameters,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Ref string `json:"ref,omitempty"` // The ref (branch or tag) of the workflow file to use + 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 +} + +// 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)." + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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. + 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)." + Previous_marketplace_purchase Webhookspreviousmarketplacepurchase `json:"previous_marketplace_purchase,omitempty"` + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + 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 { + 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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 { + Id int `json:"id"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Browser_download_url string `json:"browser_download_url"` + Created_at string `json:"created_at"` + Label string `json:"label"` + Uploader GeneratedType `json:"uploader"` // A GitHub user. + Content_type string `json:"content_type"` + Digest string `json:"digest"` + Name string `json:"name"` // The file name of the asset. + State string `json:"state"` // State of the release asset. + Size int `json:"size"` + Updated_at string `json:"updated_at"` + Download_count int `json:"download_count"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Body string `json:"body"` + Html_url string `json:"html_url"` + Path string `json:"path"` + Reactions GeneratedType `json:"reactions,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. + Commit_id string `json:"commit_id"` + Created_at string `json:"created_at"` + Id int `json:"id"` + Line int `json:"line"` + Node_id string `json:"node_id"` + Position int `json:"position"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + 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 { + Comments int `json:"comments"` + Deletions int `json:"deletions"` + Mergeable_state string `json:"mergeable_state"` + Id int64 `json:"id"` + Additions int `json:"additions"` + Base map[string]interface{} `json:"base"` + Closed_at string `json:"closed_at"` + Diff_url string `json:"diff_url"` + User GeneratedType `json:"user"` // A GitHub user. + Draft bool `json:"draft,omitempty"` // Indicates whether or not the pull request is a draft. + Requested_reviewers []GeneratedType `json:"requested_reviewers,omitempty"` + Requested_teams []GeneratedType `json:"requested_teams,omitempty"` + Patch_url string `json:"patch_url"` + Auto_merge GeneratedType `json:"auto_merge"` // The status of auto merging a pull request. + Head map[string]interface{} `json:"head"` + Html_url string `json:"html_url"` + Labels []map[string]interface{} `json:"labels"` + Number int `json:"number"` // Number uniquely identifying the pull request within its repository. + Review_comment_url string `json:"review_comment_url"` + Title string `json:"title"` // The title of the pull request. + Issue_url string `json:"issue_url"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Mergeable bool `json:"mergeable"` + Url string `json:"url"` + Merged_by GeneratedType `json:"merged_by"` // A GitHub user. + Maintainer_can_modify bool `json:"maintainer_can_modify"` // Indicates whether maintainers can modify the pull request. + State string `json:"state"` // State of this Pull Request. Either `open` or `closed`. + Comments_url string `json:"comments_url"` + Commits_url string `json:"commits_url"` + Links map[string]interface{} `json:"_links"` + Review_comments_url string `json:"review_comments_url"` + Updated_at string `json:"updated_at"` + Changed_files int `json:"changed_files"` + Node_id string `json:"node_id"` + Body string `json:"body"` + Locked bool `json:"locked"` + Merged_at string `json:"merged_at"` + Review_comments int `json:"review_comments"` + Statuses_url string `json:"statuses_url"` + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Commits int `json:"commits"` + Created_at string `json:"created_at"` + Merge_commit_sha string `json:"merge_commit_sha"` + Rebaseable bool `json:"rebaseable,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Merged bool `json:"merged"` + 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 { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + Repository_name string `json:"repository_name"` +} + +// 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 { + 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 { + 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)." + 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 { + 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. + 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. + 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. + 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_expired bool `json:"token_expired"` // Whether the associated fine-grained personal access token has expired. + Owner GeneratedType `json:"owner"` // A GitHub user. + Access_granted_at string `json:"access_granted_at"` // Date and time when the fine-grained personal access token was approved to access the organization. + 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. + Permissions map[string]interface{} `json:"permissions"` // Permissions requested, categorized by type of permission. + 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 { + 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. + 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. +} + +// 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 { + 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 { + Name string `json:"name"` + Links map[string]interface{} `json:"_links"` + Path string `json:"path"` + Sha string `json:"sha"` + TypeField string `json:"type"` + Html_url string `json:"html_url"` + Url string `json:"url"` + Download_url string `json:"download_url"` + Git_url string `json:"git_url"` + Size int `json:"size"` + Target string `json:"target"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Sub_issue_id float64 `json:"sub_issue_id"` // The ID of the sub-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. + 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. + Sub_issue Issue `json:"sub_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Sub_issue_repo Repository `json:"sub_issue_repo"` // A repository on GitHub. + Action string `json:"action"` + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// 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"` + Marketplace_pending_change map[string]interface{} `json:"marketplace_pending_change,omitempty"` + 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"` +} + +// 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"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id"` + Commit_url string `json:"commit_url"` + Event string `json:"event"` + Lock_reason string `json:"lock_reason"` + Node_id string `json:"node_id"` + Actor GeneratedType `json:"actor"` // A GitHub user. + 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. + Url string `json:"url"` + Commit_id string `json:"commit_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Released string `json:"released"` + Created_at string `json:"created_at"` + Name string `json:"name"` + Description string `json:"description"` + Logo_url string `json:"logo_url,omitempty"` + Score float64 `json:"score"` + Featured bool `json:"featured"` + Curated bool `json:"curated"` + Updated_at string `json:"updated_at"` + Related []map[string]interface{} `json:"related,omitempty"` + Aliases []map[string]interface{} `json:"aliases,omitempty"` + Created_by string `json:"created_by"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Short_description string `json:"short_description"` + Repository_count int `json:"repository_count,omitempty"` + Display_name string `json:"display_name"` +} + +// 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. + Sponsorship Webhookssponsorship `json:"sponsorship"` + 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"` + 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. + Changes Webhookschanges8 `json:"changes"` + 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)." +} + +// Webhooksprojectcolumn represents the Webhooksprojectcolumn schema from the OpenAPI specification +type Webhooksprojectcolumn struct { + Updated_at string `json:"updated_at"` + Url string `json:"url"` + After_id int `json:"after_id,omitempty"` + Cards_url string `json:"cards_url"` + Id int `json:"id"` // The unique identifier of the project column + Node_id string `json:"node_id"` + Name string `json:"name"` // Name of the project column + Created_at string `json:"created_at"` + Project_url string `json:"project_url"` +} + +// 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"` +} + +// 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 { + Id int `json:"id"` // A unique identifier of the repository. + Name string `json:"name"` // The name of the repository. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Permissions string `json:"permissions"` // The permission associated with the invitation. + Repository GeneratedType `json:"repository"` // Minimal Repository + Url string `json:"url"` // URL for the repository invitation + Created_at string `json:"created_at"` + Expired bool `json:"expired,omitempty"` // Whether or not the invitation has expired + Id int64 `json:"id"` // Unique identifier of the repository invitation. + Inviter GeneratedType `json:"inviter"` // A GitHub user. + Html_url string `json:"html_url"` + Invitee GeneratedType `json:"invitee"` // A GitHub user. + Node_id string `json:"node_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. + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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 { + Merge_type string `json:"merge_type,omitempty"` + Message string `json:"message,omitempty"` + Base_branch string `json:"base_branch,omitempty"` +} + +// Webhooksmilestone3 represents the Webhooksmilestone3 schema from the OpenAPI specification +type Webhooksmilestone3 struct { + Title string `json:"title"` // The title of the milestone. + Id int `json:"id"` + Created_at string `json:"created_at"` + Closed_issues int `json:"closed_issues"` + Labels_url string `json:"labels_url"` + Open_issues int `json:"open_issues"` + Number int `json:"number"` // The number of the milestone. + Updated_at string `json:"updated_at"` + Node_id string `json:"node_id"` + Html_url string `json:"html_url"` + Description string `json:"description"` + State string `json:"state"` // The state of the milestone. + Due_on string `json:"due_on"` + Closed_at string `json:"closed_at"` + Creator map[string]interface{} `json:"creator"` + Url string `json:"url"` +} + +// 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 { + 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 { + Event string `json:"event,omitempty"` // The event that triggered the deployment protection rule. + 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"` + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Action string `json:"action,omitempty"` + Deployment Deployment `json:"deployment,omitempty"` // A request for a specific ref(branch,sha,tag) to be deployed + Deployment_callback_url string `json:"deployment_callback_url,omitempty"` // The URL to review the deployment protection rule. + Environment string `json:"environment,omitempty"` // The name of the environment that has the deployment protection rule. + 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. +} + +// 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"` + 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. +} + +// Language represents the Language schema from the OpenAPI specification +type Language struct { +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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 { + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Subscribers_url string `json:"subscribers_url"` + Languages_url string `json:"languages_url"` + Releases_url string `json:"releases_url"` + Has_wiki bool `json:"has_wiki"` // Whether the wiki is enabled. + Forks_url string `json:"forks_url"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Issue_events_url string `json:"issue_events_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. + Notifications_url string `json:"notifications_url"` + 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"` + Has_projects bool `json:"has_projects"` // Whether projects are enabled. + 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. + 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. + Forks int `json:"forks"` + License GeneratedType `json:"license"` // License Simple + Is_template bool `json:"is_template,omitempty"` // Whether this repository acts as a template that can be used to generate new repositories. + Labels_url string `json:"labels_url"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` // Whether to allow rebase merges for pull requests. + Pulls_url string `json:"pulls_url"` + Updated_at string `json:"updated_at"` + Assignees_url string `json:"assignees_url"` + Comments_url string `json:"comments_url"` + Stargazers_url string `json:"stargazers_url"` + Clone_url string `json:"clone_url"` + Archive_url string `json:"archive_url"` + Has_pages bool `json:"has_pages"` + Has_downloads bool `json:"has_downloads"` // Whether downloads are enabled. + Keys_url string `json:"keys_url"` + Name string `json:"name"` // The name of the repository. + 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. + Archived bool `json:"archived"` // Whether the repository is archived. + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` // Whether to allow merge commits for pull requests. + Has_discussions bool `json:"has_discussions,omitempty"` // Whether discussions are enabled. + Contributors_url string `json:"contributors_url"` + Events_url string `json:"events_url"` + Private bool `json:"private"` // Whether the repository is private or public. + Svn_url string `json:"svn_url"` + Git_url string `json:"git_url"` + Html_url string `json:"html_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). + Tags_url string `json:"tags_url"` + Created_at string `json:"created_at"` + Blobs_url string `json:"blobs_url"` + Git_commits_url string `json:"git_commits_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` // Whether to allow Auto-merge to be used on pull requests. + 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. + Branches_url string `json:"branches_url"` + Forks_count int `json:"forks_count"` + Milestones_url string `json:"milestones_url"` + Ssh_url string `json:"ssh_url"` + Downloads_url string `json:"downloads_url"` + Subscription_url string `json:"subscription_url"` + Description string `json:"description"` + Watchers_count int `json:"watchers_count"` + Node_id string `json:"node_id"` + Allow_forking bool `json:"allow_forking,omitempty"` // Whether to allow forking this repo + Contents_url string `json:"contents_url"` + Trees_url string `json:"trees_url"` + Stargazers_count int `json:"stargazers_count"` + Homepage string `json:"homepage"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Issues_url string `json:"issues_url"` + Merges_url string `json:"merges_url"` + Deployments_url string `json:"deployments_url"` + Git_refs_url string `json:"git_refs_url"` + Hooks_url string `json:"hooks_url"` + Organization GeneratedType `json:"organization,omitempty"` // A GitHub user. + Watchers int `json:"watchers"` + Anonymous_access_enabled bool `json:"anonymous_access_enabled,omitempty"` // Whether anonymous git access is enabled for this repository + 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. + Open_issues_count int `json:"open_issues_count"` + Topics []string `json:"topics,omitempty"` + 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 + Open_issues int `json:"open_issues"` + Git_tags_url string `json:"git_tags_url"` + Url string `json:"url"` + Fork bool `json:"fork"` + Teams_url string `json:"teams_url"` + Commits_url string `json:"commits_url"` + Language string `json:"language"` + Statuses_url string `json:"statuses_url"` + Subscribers_count int `json:"subscribers_count,omitempty"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Full_name string `json:"full_name"` + Template_repository map[string]interface{} `json:"template_repository,omitempty"` + Collaborators_url string `json:"collaborators_url"` + Master_branch string `json:"master_branch,omitempty"` + Id int64 `json:"id"` // Unique identifier of the repository + 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). + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Starred_at string `json:"starred_at,omitempty"` + Compare_url string `json:"compare_url"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Has_issues bool `json:"has_issues"` // Whether issues are enabled. + Issue_comment_url string `json:"issue_comment_url"` + Network_count int `json:"network_count,omitempty"` + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` // Whether to allow squash merges for pull requests. + Pushed_at string `json:"pushed_at"` +} + +// 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 { + Id int `json:"id"` + Review_requester GeneratedType `json:"review_requester"` // A GitHub user. + Commit_id string `json:"commit_id"` + 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. + Requested_team Team `json:"requested_team,omitempty"` // Groups of organization members that gives permissions on specified repositories. + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Requested_reviewer GeneratedType `json:"requested_reviewer,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` // The REST API URL of the alert resource. + Created_at string `json:"created_at"` // The time that the alert was created 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. + Dismissed_comment string `json:"dismissed_comment,omitempty"` // The dismissal comment associated with the dismissal of the alert. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Dismissed_reason string `json:"dismissed_reason"` // **Required when the state is dismissed.** The reason for dismissing or closing the alert. + Rule GeneratedType `json:"rule"` + Dismissal_approved_by GeneratedType `json:"dismissal_approved_by,omitempty"` // A GitHub user. + Most_recent_instance GeneratedType `json:"most_recent_instance"` + Instances_url string `json:"instances_url"` // The REST API URL for fetching the list of instances for an alert. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + 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`. + Dismissed_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Tool GeneratedType `json:"tool"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Runner_type string `json:"runner_type,omitempty"` // Runner type to be used. + Schedule string `json:"schedule,omitempty"` // The frequency of the periodic analysis. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Body_html string `json:"body_html,omitempty"` + Event string `json:"event"` + Submitted_at string `json:"submitted_at,omitempty"` + Body string `json:"body"` // The text of the review. + State string `json:"state"` + User GeneratedType `json:"user"` // A GitHub user. + Links map[string]interface{} `json:"_links"` + Body_text string `json:"body_text,omitempty"` + Id int `json:"id"` // Unique identifier of the review + Pull_request_url string `json:"pull_request_url"` + Commit_id string `json:"commit_id"` // A commit SHA for the review. +} + +// Collaborator represents the Collaborator schema from the OpenAPI specification +type Collaborator struct { + Site_admin bool `json:"site_admin"` + Login string `json:"login"` + Subscriptions_url string `json:"subscriptions_url"` + TypeField string `json:"type"` + User_view_type string `json:"user_view_type,omitempty"` + Id int64 `json:"id"` + Events_url string `json:"events_url"` + Followers_url string `json:"followers_url"` + Repos_url string `json:"repos_url"` + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Gists_url string `json:"gists_url"` + Email string `json:"email,omitempty"` + Name string `json:"name,omitempty"` + Organizations_url string `json:"organizations_url"` + Role_name string `json:"role_name"` + Starred_url string `json:"starred_url"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` + Received_events_url string `json:"received_events_url"` + Following_url string `json:"following_url"` + Gravatar_id string `json:"gravatar_id"` +} + +// Event represents the Event schema from the OpenAPI specification +type Event struct { + 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"` + Id string `json:"id"` + Org Actor `json:"org,omitempty"` // Actor +} + +// 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 { + 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 { + 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. + Id int64 `json:"id"` // The unique identifier of the role. + 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. + Description string `json:"description,omitempty"` // A short description about who this role is for or what permissions it grants. + 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. +} + +// 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 { + 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 { + Spdx_id string `json:"spdx_id"` + 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"` +} + +// 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 { + 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"` + Documentation_url string `json:"documentation_url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description"` // The description of an autofix. + 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. +} + +// 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 { + 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. + Private bool `json:"private"` // Whether the repository is private. + Default_branch string `json:"default_branch"` // The default branch for the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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 { + Runner_label string `json:"runner_label,omitempty"` // Runner label to be used if the runner type is labeled. + 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. +} + +// 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. + Parent_issue_id float64 `json:"parent_issue_id"` // The ID of the parent issue. + 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)." + 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_id float64 `json:"sub_issue_id"` // The ID of the sub-issue. + Parent_issue Issue `json:"parent_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + 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 { + 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"` // A GitHub user. + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + 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. + 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. + 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)." +} + +// Project represents the Project schema from the OpenAPI specification +type Project struct { + State string `json:"state"` // State of the project; either 'open' or 'closed' + Body string `json:"body"` // Body of the project + Private bool `json:"private,omitempty"` // Whether or not this project can be seen by everyone. Only present if owner is an organization. + Created_at string `json:"created_at"` + Id int `json:"id"` + Creator GeneratedType `json:"creator"` // A GitHub user. + 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. + Html_url string `json:"html_url"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Name string `json:"name"` // Name of the project + Number int `json:"number"` + Columns_url string `json:"columns_url"` + Node_id string `json:"node_id"` + Owner_url string `json:"owner_url"` +} + +// 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 { + Context string `json:"context"` + Id int `json:"id"` + State string `json:"state"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` + Description string `json:"description"` + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Required bool `json:"required,omitempty"` + Target_url string `json:"target_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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. +} + +// 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. + Milestone Webhooksmilestone `json:"milestone,omitempty"` // A collection of related issues and pull requests. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Deleted_at string `json:"deleted_at,omitempty"` + License string `json:"license,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Url string `json:"url"` + Html_url string `json:"html_url,omitempty"` + Id int `json:"id"` // Unique identifier of the package version. + Description string `json:"description,omitempty"` + Name string `json:"name"` // The name of the package version. + Package_html_url string `json:"package_html_url"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Invitation_teams_url string `json:"invitation_teams_url"` + Failed_at string `json:"failed_at,omitempty"` + Node_id string `json:"node_id"` + Team_count int `json:"team_count"` + Failed_reason string `json:"failed_reason,omitempty"` + Login string `json:"login"` + Role string `json:"role"` + Created_at string `json:"created_at"` + Email string `json:"email"` + Invitation_source string `json:"invitation_source,omitempty"` + Inviter GeneratedType `json:"inviter"` // A GitHub user. + Id int64 `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"` // 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"` +} + +// 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"` + 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)." +} + +// Root represents the Root schema from the OpenAPI specification +type Root struct { + Issue_search_url string `json:"issue_search_url"` + Current_user_repositories_url string `json:"current_user_repositories_url"` + User_repositories_url string `json:"user_repositories_url"` + Hub_url string `json:"hub_url,omitempty"` + Public_gists_url string `json:"public_gists_url"` + Events_url string `json:"events_url"` + Code_search_url string `json:"code_search_url"` + Organization_repositories_url string `json:"organization_repositories_url"` + User_url string `json:"user_url"` + Emails_url string `json:"emails_url"` + Feeds_url string `json:"feeds_url"` + User_search_url string `json:"user_search_url"` + Starred_url string `json:"starred_url"` + Organization_url string `json:"organization_url"` + User_organizations_url string `json:"user_organizations_url"` + Followers_url string `json:"followers_url"` + Topic_search_url string `json:"topic_search_url,omitempty"` + Keys_url string `json:"keys_url"` + Current_user_url string `json:"current_user_url"` + Repository_url string `json:"repository_url"` + Gists_url string `json:"gists_url"` + Issues_url string `json:"issues_url"` + Commit_search_url string `json:"commit_search_url"` + Starred_gists_url string `json:"starred_gists_url"` + Current_user_authorizations_html_url string `json:"current_user_authorizations_html_url"` + Label_search_url string `json:"label_search_url"` + Notifications_url string `json:"notifications_url"` + Repository_search_url string `json:"repository_search_url"` + Emojis_url string `json:"emojis_url"` + Following_url string `json:"following_url"` + Organization_teams_url string `json:"organization_teams_url"` + Rate_limit_url string `json:"rate_limit_url"` + Authorizations_url string `json:"authorizations_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the secret. + Updated_at string `json:"updated_at"` +} + +// 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 { + Issue_comment_url string `json:"issue_comment_url"` // The API URL to get the issue comment where the secret was detected. +} + +// 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"` + Comment Webhookscomment `json:"comment"` +} + +// 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,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. +} + +// 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,omitempty"` + Enforcement_level string `json:"enforcement_level,omitempty"` + Strict bool `json:"strict,omitempty"` + Url string `json:"url,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + 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. + Requester Webhooksuser `json:"requester"` + 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)." + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` + Repositories_added []map[string]interface{} `json:"repositories_added"` // An array of repository objects, which were added to the installation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Website_url string `json:"website_url,omitempty"` // The enterprise's website URL. + Html_url string `json:"html_url"` + Id int `json:"id"` // Unique identifier of the enterprise + Avatar_url string `json:"avatar_url"` + Name string `json:"name"` // The name of the enterprise. + Created_at string `json:"created_at"` + Description string `json:"description,omitempty"` // A short description of the enterprise. + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Slug string `json:"slug"` // The slug url identifier for the enterprise. +} + +// 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 { + 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. + Status string `json:"status"` +} + +// 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)." + 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. + 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. + 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 { + 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"` + 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)." +} + +// 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. + 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. +} + +// 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 { + 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 { + Review_id int `json:"review_id"` + State string `json:"state"` + Dismissal_commit_id string `json:"dismissal_commit_id,omitempty"` + Dismissal_message string `json:"dismissal_message"` +} + +// 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)." + 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. + 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. + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Statuses_url string `json:"statuses_url"` + Merge_commit_sha string `json:"merge_commit_sha"` + Merged_at string `json:"merged_at"` + Labels []map[string]interface{} `json:"labels"` + User GeneratedType `json:"user"` // A GitHub user. + Body string `json:"body"` + Html_url string `json:"html_url"` + Draft bool `json:"draft,omitempty"` // Indicates whether or not the pull request is a draft. + Review_comments_url string `json:"review_comments_url"` + Auto_merge GeneratedType `json:"auto_merge"` // The status of auto merging a pull request. + Closed_at string `json:"closed_at"` + Created_at string `json:"created_at"` + State string `json:"state"` + Url string `json:"url"` + Diff_url string `json:"diff_url"` + Requested_teams []Team `json:"requested_teams,omitempty"` + Comments_url string `json:"comments_url"` + Review_comment_url string `json:"review_comment_url"` + Number int `json:"number"` + Locked bool `json:"locked"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Assignees []GeneratedType `json:"assignees,omitempty"` + Issue_url string `json:"issue_url"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Id int64 `json:"id"` + Title string `json:"title"` + Node_id string `json:"node_id"` + Patch_url string `json:"patch_url"` + Links map[string]interface{} `json:"_links"` + Base map[string]interface{} `json:"base"` + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Head map[string]interface{} `json:"head"` + Requested_reviewers []GeneratedType `json:"requested_reviewers,omitempty"` + Commits_url string `json:"commits_url"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Merge_base_commit Commit `json:"merge_base_commit"` // Commit + Status string `json:"status"` + Total_commits int `json:"total_commits"` + Url string `json:"url"` + Behind_by int `json:"behind_by"` + Diff_url string `json:"diff_url"` + Files []GeneratedType `json:"files,omitempty"` + Html_url string `json:"html_url"` + Patch_url string `json:"patch_url"` + Base_commit Commit `json:"base_commit"` // Commit + Commits []Commit `json:"commits"` + Permalink_url string `json:"permalink_url"` + Ahead_by int `json:"ahead_by"` +} + +// 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 { + Action string `json:"action"` + 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"` +} + +// 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 { + 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)." + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Protected bool `json:"protected"` + Protection GeneratedType `json:"protection,omitempty"` // Branch Protection + Protection_url string `json:"protection_url,omitempty"` + Commit map[string]interface{} `json:"commit"` + Name string `json:"name"` +} + +// 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 { + 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. + Architecture string `json:"architecture"` + Download_url string `json:"download_url"` + Filename string `json:"filename"` + Os string `json:"os"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Configuration GeneratedType `json:"configuration,omitempty"` // A code security configuration + 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 { + 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 { + 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`. + 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)." + Validity string `json:"validity,omitempty"` // The token status as of the latest validity check. + Html_url string `json:"html_url,omitempty"` // The GitHub URL of the alert resource. + Resolution_comment string `json:"resolution_comment,omitempty"` // An optional comment to resolve an alert. + Secret_type string `json:"secret_type,omitempty"` // The type of secret that secret scanning detected. + 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_html_url string `json:"push_protection_bypass_request_html_url,omitempty"` // The URL to a push protection bypass request. + Number int `json:"number,omitempty"` // The security alert number. + Push_protection_bypassed bool `json:"push_protection_bypassed,omitempty"` // Whether push protection was bypassed for the detected secret. + 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 in the same organization or business. + Url string `json:"url,omitempty"` // The REST API URL of the alert resource. + Publicly_leaked bool `json:"publicly_leaked,omitempty"` // Whether the detected secret was publicly leaked. + 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. + Push_protection_bypass_request_reviewer GeneratedType `json:"push_protection_bypass_request_reviewer,omitempty"` // A GitHub user. + Resolution string `json:"resolution,omitempty"` // The reason for resolving the alert. + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Locations_url string `json:"locations_url,omitempty"` // The REST API URL of the code locations for this alert. + Push_protection_bypass_request_reviewer_comment string `json:"push_protection_bypass_request_reviewer_comment,omitempty"` // An optional comment when reviewing a push protection bypass. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Storage_in_bytes int `json:"storage_in_bytes"` // How much storage is available to the codespace. +} + +// Environment represents the Environment schema from the OpenAPI specification +type Environment struct { + Updated_at string `json:"updated_at"` // The time that the environment was last updated, in ISO 8601 format. + Url string `json:"url"` + Id int64 `json:"id"` // The id of the environment. + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` // The time that the environment was created, in ISO 8601 format. + Html_url string `json:"html_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`. + Protection_rules []interface{} `json:"protection_rules,omitempty"` // Built-in deployment protection rules for the environment. + Name string `json:"name"` // The name of the environment. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Size int `json:"size"` + TypeField string `json:"type"` + Content string `json:"content"` + Download_url string `json:"download_url"` + Url string `json:"url"` + Encoding string `json:"encoding"` + Html_url string `json:"html_url"` + Links map[string]interface{} `json:"_links"` + License GeneratedType `json:"license"` // License Simple + Sha string `json:"sha"` + Git_url string `json:"git_url"` + Name string `json:"name"` + Path string `json:"path"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + State_reason string `json:"state_reason,omitempty"` // The reason for the current state + Repository_url string `json:"repository_url"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Body string `json:"body,omitempty"` // Contents of the issue + Sub_issues_summary GeneratedType `json:"sub_issues_summary,omitempty"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Comments int `json:"comments"` + Title string `json:"title"` // Title of the issue + Body_html string `json:"body_html,omitempty"` + Url string `json:"url"` // URL for the issue + Html_url string `json:"html_url"` + Draft bool `json:"draft,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Events_url string `json:"events_url"` + Created_at string `json:"created_at"` + Reactions GeneratedType `json:"reactions,omitempty"` + Closed_by GeneratedType `json:"closed_by,omitempty"` // A GitHub user. + Number int `json:"number"` // Number uniquely identifying the issue within its repository + Repository Repository `json:"repository,omitempty"` // A repository on GitHub. + Updated_at string `json:"updated_at"` + Body_text string `json:"body_text,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"` + Node_id string `json:"node_id"` + Comments_url string `json:"comments_url"` + Locked bool `json:"locked"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + 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 + Assignees []GeneratedType `json:"assignees,omitempty"` + State string `json:"state"` // State of the issue; either 'open' or 'closed' + Timeline_url string `json:"timeline_url,omitempty"` + Labels_url string `json:"labels_url"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Closed_at string `json:"closed_at"` +} + +// 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 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 + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Billable map[string]interface{} `json:"billable"` +} + +// 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_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"` +} + +// 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"` + Notification_setting string `json:"notification_setting,omitempty"` // Whether team members will receive notifications when their team is @mentioned + Url string `json:"url,omitempty"` // URL for the team + Id int `json:"id"` // Unique identifier of the team + Members_url string `json:"members_url,omitempty"` + Privacy string `json:"privacy,omitempty"` + Node_id string `json:"node_id,omitempty"` + Permission string `json:"permission,omitempty"` // Permission that the team will have for its repositories + Repositories_url string `json:"repositories_url,omitempty"` + 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 { + 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 { + 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"` + 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. + Actor GeneratedType `json:"actor"` // A GitHub user. + Id int `json:"id"` + Milestone map[string]interface{} `json:"milestone"` +} + +// 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 { + Public_gists int `json:"public_gists"` + Updated_at string `json:"updated_at"` + Starred_url string `json:"starred_url"` + Bio string `json:"bio"` + Login string `json:"login"` + TypeField string `json:"type"` + Plan map[string]interface{} `json:"plan,omitempty"` + Id int64 `json:"id"` + Collaborators int `json:"collaborators,omitempty"` + Site_admin bool `json:"site_admin"` + Gravatar_id string `json:"gravatar_id"` + Url string `json:"url"` + Disk_usage int `json:"disk_usage,omitempty"` + Following int `json:"following"` + User_view_type string `json:"user_view_type,omitempty"` + Notification_email string `json:"notification_email,omitempty"` + Events_url string `json:"events_url"` + Following_url string `json:"following_url"` + Owned_private_repos int `json:"owned_private_repos,omitempty"` + Twitter_username string `json:"twitter_username,omitempty"` + Hireable bool `json:"hireable"` + Blog string `json:"blog"` + Private_gists int `json:"private_gists,omitempty"` + Public_repos int `json:"public_repos"` + Followers int `json:"followers"` + Location string `json:"location"` + Total_private_repos int `json:"total_private_repos,omitempty"` + Name string `json:"name"` + Received_events_url string `json:"received_events_url"` + Organizations_url string `json:"organizations_url"` + Html_url string `json:"html_url"` + Subscriptions_url string `json:"subscriptions_url"` + Company string `json:"company"` + Repos_url string `json:"repos_url"` + Avatar_url string `json:"avatar_url"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Gists_url string `json:"gists_url"` + Email string `json:"email"` + Followers_url string `json:"followers_url"` +} + +// Artifact represents the Artifact schema from the OpenAPI specification +type Artifact struct { + Expired bool `json:"expired"` // Whether or not the artifact has expired. + Expires_at string `json:"expires_at"` + Node_id string `json:"node_id"` + Workflow_run map[string]interface{} `json:"workflow_run,omitempty"` + Created_at string `json:"created_at"` + Name string `json:"name"` // The name of the artifact. + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Id int `json:"id"` + Size_in_bytes int `json:"size_in_bytes"` // The size in bytes of the artifact. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Expires_at string `json:"expires_at"` + Has_multiple_single_files bool `json:"has_multiple_single_files,omitempty"` + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Dependencies []map[string]interface{} `json:"dependencies,omitempty"` + Version_info map[string]interface{} `json:"version_info,omitempty"` + Commit_oid string `json:"commit_oid,omitempty"` + Homepage string `json:"homepage,omitempty"` + Metadata map[string]interface{} `json:"metadata,omitempty"` + Name string `json:"name,omitempty"` + Platform string `json:"platform,omitempty"` + Description string `json:"description,omitempty"` + Readme string `json:"readme,omitempty"` + Repo string `json:"repo,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + State string `json:"state"` + Statuses []GeneratedType `json:"statuses"` + Total_count int `json:"total_count"` + Url string `json:"url"` + Commit_url string `json:"commit_url"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Sha string `json:"sha"` +} + +// 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)." + Label Webhookslabel `json:"label"` +} + +// 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"` // Determines if all notifications should be blocked from this repository. + Reason string `json:"reason"` + Repository_url string `json:"repository_url"` + Subscribed bool `json:"subscribed"` // Determines if notifications should be received from this repository. +} + +// 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Status string `json:"status"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + 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. +} + +// 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)." + Sender GeneratedType `json:"sender"` // A GitHub user. + Comment Webhookscomment `json:"comment"` + 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. + Changes map[string]interface{} `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. + Action string `json:"action"` + Discussion Discussion `json:"discussion"` // A Discussion in a repository. +} + +// 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 { + 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)." + Alert map[string]interface{} `json:"alert"` // The code scanning alert involved in the event. + 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. + 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 { + 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. + Node_id string `json:"node_id"` // The node ID for the deployment protection rule. +} + +// Discussion represents the Discussion schema from the OpenAPI specification +type Discussion struct { + Html_url string `json:"html_url"` + Title string `json:"title"` + Comments int `json:"comments"` + Created_at string `json:"created_at"` + User map[string]interface{} `json:"user"` + Answer_chosen_by map[string]interface{} `json:"answer_chosen_by"` + Answer_html_url string `json:"answer_html_url"` + Category map[string]interface{} `json:"category"` + Locked bool `json:"locked"` + Labels []Label `json:"labels,omitempty"` + Id int `json:"id"` + Number int `json:"number"` + Repository_url string `json:"repository_url"` + Node_id string `json:"node_id"` + Reactions map[string]interface{} `json:"reactions,omitempty"` + 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. + Answer_chosen_at string `json:"answer_chosen_at"` + Active_lock_reason string `json:"active_lock_reason"` + State_reason string `json:"state_reason"` // The reason for the current state + Timeline_url string `json:"timeline_url,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Updated_at string `json:"updated_at"` + Body string `json:"body"` +} + +// 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 { + Base map[string]interface{} `json:"base"` + Closed_at string `json:"closed_at"` + Diff_url string `json:"diff_url"` + User GeneratedType `json:"user"` // A GitHub user. + Draft bool `json:"draft,omitempty"` // Indicates whether or not the pull request is a draft. + Requested_reviewers []GeneratedType `json:"requested_reviewers,omitempty"` + Requested_teams []GeneratedType `json:"requested_teams,omitempty"` + Patch_url string `json:"patch_url"` + Auto_merge GeneratedType `json:"auto_merge"` // The status of auto merging a pull request. + Head map[string]interface{} `json:"head"` + Html_url string `json:"html_url"` + Labels []map[string]interface{} `json:"labels"` + Number int `json:"number"` // Number uniquely identifying the pull request within its repository. + Review_comment_url string `json:"review_comment_url"` + Title string `json:"title"` // The title of the pull request. + Issue_url string `json:"issue_url"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Mergeable bool `json:"mergeable"` + Url string `json:"url"` + Merged_by GeneratedType `json:"merged_by"` // A GitHub user. + Maintainer_can_modify bool `json:"maintainer_can_modify"` // Indicates whether maintainers can modify the pull request. + State string `json:"state"` // State of this Pull Request. Either `open` or `closed`. + Comments_url string `json:"comments_url"` + Commits_url string `json:"commits_url"` + Links map[string]interface{} `json:"_links"` + Review_comments_url string `json:"review_comments_url"` + Updated_at string `json:"updated_at"` + Changed_files int `json:"changed_files"` + Node_id string `json:"node_id"` + Body string `json:"body"` + Locked bool `json:"locked"` + Merged_at string `json:"merged_at"` + Review_comments int `json:"review_comments"` + Statuses_url string `json:"statuses_url"` + Active_lock_reason string `json:"active_lock_reason,omitempty"` + Commits int `json:"commits"` + Created_at string `json:"created_at"` + Merge_commit_sha string `json:"merge_commit_sha"` + Rebaseable bool `json:"rebaseable,omitempty"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Merged bool `json:"merged"` + Comments int `json:"comments"` + Deletions int `json:"deletions"` + Mergeable_state string `json:"mergeable_state"` + Id int64 `json:"id"` + Additions int `json:"additions"` +} + +// 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,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. +} + +// 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 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. + 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)." + 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. + Changes Webhookschanges `json:"changes"` // The changes to the comment. + Comment Webhooksissuecomment `json:"comment"` // The [comment](https://docs.github.com/rest/issues/comments#get-an-issue-comment) itself. + Action string `json:"action"` +} + +// 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. + Action string `json:"action"` + Pull_request map[string]interface{} `json:"pull_request"` + Review Webhooksreview `json:"review"` // The review that was affected. + 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. + 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 map[string]interface{} `json:"changes"` +} + +// 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. + Slug string `json:"slug"` // Sluggified name of the 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. + Max_members int `json:"max_members"` // The maximum allowable members per team. + Classroom Classroom `json:"classroom"` // A GitHub Classroom classroom + Passing int `json:"passing"` // The number of students that have passed 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. + Language string `json:"language"` // The programming language used in the assignment. + Editor string `json:"editor"` // The selected editor for the assignment. + Submitted int `json:"submitted"` // The number of students that have submitted the assignment. + Id int `json:"id"` // Unique identifier of the repository. + 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. + Title string `json:"title"` // Assignment title. + TypeField string `json:"type"` // Whether it's a group assignment or individual assignment. + Max_teams int `json:"max_teams"` // The maximum allowable teams for the assignment. + Starter_code_repository GeneratedType `json:"starter_code_repository"` // A GitHub repository view for Classroom + Accepted int `json:"accepted"` // The number of students that have accepted the assignment. +} + +// 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 { + 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. + 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. +} + +// Webhooksalert represents the Webhooksalert schema from the OpenAPI specification +type Webhooksalert struct { + State string `json:"state"` + Fix_reason string `json:"fix_reason,omitempty"` + Ghsa_id string `json:"ghsa_id"` + Affected_range string `json:"affected_range"` + Created_at string `json:"created_at"` + Fixed_in string `json:"fixed_in,omitempty"` + Affected_package_name string `json:"affected_package_name"` + Dismiss_reason string `json:"dismiss_reason,omitempty"` + External_reference string `json:"external_reference"` + Node_id string `json:"node_id"` + Dismissed_at string `json:"dismissed_at,omitempty"` + Severity string `json:"severity"` + Dismisser map[string]interface{} `json:"dismisser,omitempty"` + Number int `json:"number"` + Fixed_at string `json:"fixed_at,omitempty"` + Id int `json:"id"` + External_identifier string `json:"external_identifier"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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. +} + +// 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 map[string]interface{} `json:"workflow_job"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Wait_timer_started_at string `json:"wait_timer_started_at"` // The time that the wait timer began. + 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 +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Description string `json:"description,omitempty"` + Group_name string `json:"group_name,omitempty"` + Name string `json:"name"` + Organization_selection_type string `json:"organization_selection_type,omitempty"` + Html_url string `json:"html_url"` + Id int64 `json:"id"` + Members_url string `json:"members_url"` + Slug string `json:"slug"` + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Group_id string `json:"group_id,omitempty"` + Sync_to_organizations string `json:"sync_to_organizations,omitempty"` +} + +// 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"` + 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 { + 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 { + Source string `json:"source,omitempty"` // The source of the repository property. Defaults to 'custom' if not specified. + 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 +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` // The GraphQL identifier of the repository. + Html_url string `json:"html_url"` // The URL to view the repository on GitHub.com. + Owner GeneratedType `json:"owner"` // A GitHub user. + 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. + Downloads_url string `json:"downloads_url"` // The API URL to list the downloads on the repository. + Commits_url string `json:"commits_url"` // A template for the API URL to get information about commits on the repository. + Full_name string `json:"full_name"` // The full, globally unique, name of the repository. + Id int64 `json:"id"` // A unique identifier of the repository. + Subscribers_url string `json:"subscribers_url"` // The API URL to list the subscribers on the repository. + Teams_url string `json:"teams_url"` // The API URL to list the teams on the repository. + Branches_url string `json:"branches_url"` // A template for the API URL to get information about branches in the repository. + Contributors_url string `json:"contributors_url"` // A template for the API URL to list the contributors to the repository. + Merges_url string `json:"merges_url"` // The API URL to merge 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. + Statuses_url string `json:"statuses_url"` // A template for the API URL to get information about statuses of a commit. + 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. + Forks_url string `json:"forks_url"` // The API URL to list the forks of the repository. + Issues_url string `json:"issues_url"` // A template for the API URL to get information about issues on 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. + Assignees_url string `json:"assignees_url"` // A template for the API URL to list the available assignees for issues in the repository. + Tags_url string `json:"tags_url"` // The API URL to get information about tags on 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. + Name string `json:"name"` // The name of the repository. + Collaborators_url string `json:"collaborators_url"` // A template for the API URL to get information about collaborators of the repository. + Description string `json:"description"` // The repository description. + Keys_url string `json:"keys_url"` // A template for the API URL to get information about deploy keys 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. + Archive_url string `json:"archive_url"` // A template for the API URL to download the repository as an archive. + Deployments_url string `json:"deployments_url"` // The API URL to list the deployments of the repository. + Pulls_url string `json:"pulls_url"` // A template for the API URL to get information about pull requests on the repository. + Stargazers_url string `json:"stargazers_url"` // The API URL to list the stargazers on the repository. + Fork bool `json:"fork"` // Whether the repository is a fork. + Compare_url string `json:"compare_url"` // A template for the API URL to compare two commits or refs. + Contents_url string `json:"contents_url"` // A template for the API URL to get the contents of 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. + Releases_url string `json:"releases_url"` // A template for the API URL to get information about releases on the repository. + Subscription_url string `json:"subscription_url"` // The API URL to subscribe to notifications for this repository. + Milestones_url string `json:"milestones_url"` // A template for the API URL to get information about milestones of the repository. + Comments_url string `json:"comments_url"` // A template for the API URL to get information about comments on the repository. + Url string `json:"url"` // The URL to get more information about the repository from the GitHub API. + Hooks_url string `json:"hooks_url"` // The API URL to list the hooks on the repository. + Languages_url string `json:"languages_url"` // The API URL to get information about the languages 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. + Events_url string `json:"events_url"` // The API URL to list the events of the repository. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name"` // The name of the secret. + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` +} + +// 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 { + 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. + Color string `json:"color,omitempty"` // Color for the issue type. + Description string `json:"description,omitempty"` // Description of the issue type. +} + +// 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 { + Status string `json:"status,omitempty"` // The current status of the deployment. +} + +// 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 { + Repository_advisory GeneratedType `json:"repository_advisory"` // A repository security advisory. + 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"` // 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 { + Change_status map[string]interface{} `json:"change_status"` + Committed_at string `json:"committed_at"` + Url string `json:"url"` + User GeneratedType `json:"user"` // A GitHub user. + Version string `json:"version"` +} + +// Webhookssponsorship represents the Webhookssponsorship schema from the OpenAPI specification +type Webhookssponsorship struct { + 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"` + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Spdx_id string `json:"spdx_id"` + Url string `json:"url"` + Html_url string `json:"html_url,omitempty"` + Key string `json:"key"` + Name string `json:"name"` +} + +// 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 { + Author GeneratedType `json:"author"` // A GitHub user. + 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. + Reactions GeneratedType `json:"reactions,omitempty"` + Discussion_url string `json:"discussion_url"` + Html_url string `json:"html_url"` + Number int `json:"number"` // The unique sequence number of a team discussion comment. + Body_html string `json:"body_html"` + Created_at string `json:"created_at"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Body string `json:"body"` // The main text of the comment. + Last_edited_at string `json:"last_edited_at"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Id int `json:"id,omitempty"` // Unique identifier of the label. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Version string `json:"version,omitempty"` + Change_status map[string]interface{} `json:"change_status,omitempty"` + Committed_at string `json:"committed_at,omitempty"` + Url string `json:"url,omitempty"` + User GeneratedType `json:"user,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Uploader GeneratedType `json:"uploader"` // A GitHub user. + Id int `json:"id"` // The ID of the CodeQL database. + Name string `json:"name"` // The name of the CodeQL database. + 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. + 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. + Content_type string `json:"content_type"` // The MIME type of the CodeQL database file. + 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. + Language string `json:"language"` // The language of the CodeQL database. +} + +// 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,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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Git_url string `json:"git_url"` + Name string `json:"name"` + Html_url string `json:"html_url"` + Last_modified_at string `json:"last_modified_at,omitempty"` + Url string `json:"url"` + File_size int `json:"file_size,omitempty"` + Language string `json:"language,omitempty"` + Line_numbers []string `json:"line_numbers,omitempty"` + Path string `json:"path"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Score float64 `json:"score"` + Sha string `json:"sha"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 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 { + 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 { + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + Node_id string `json:"node_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. + Reactions GeneratedType `json:"reactions,omitempty"` + Body_text string `json:"body_text,omitempty"` + Issue_url string `json:"issue_url"` + Url string `json:"url"` // URL for the issue comment + 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,omitempty"` // Contents of the issue comment + Body_html string `json:"body_html,omitempty"` + Html_url string `json:"html_url"` + Id int64 `json:"id"` // Unique identifier of the issue comment +} + +// 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 { + Score float64 `json:"score"` + Url string `json:"url"` + Author GeneratedType `json:"author"` // A GitHub user. + Commit map[string]interface{} `json:"commit"` + Html_url string `json:"html_url"` + Node_id string `json:"node_id"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Sha string `json:"sha"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Comments_url string `json:"comments_url"` + Parents []map[string]interface{} `json:"parents"` + Committer GeneratedType `json:"committer"` // Metaproperties for Git author/committer information. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Commit_id string `json:"commit_id"` + Node_id string `json:"node_id"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Project_card map[string]interface{} `json:"project_card,omitempty"` + Url string `json:"url"` + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_url string `json:"commit_url"` + Id int `json:"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. +} + +// 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 { + 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 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. +} + +// 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 { + 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 + 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"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + Email string `json:"email,omitempty"` + Id int `json:"id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 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 { + 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. + Sha string `json:"sha,omitempty"` // SHA of commit with autofix. +} + +// 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. +} + +// Webhooksusermannequin represents the Webhooksusermannequin schema from the OpenAPI specification +type Webhooksusermannequin struct { + Received_events_url string `json:"received_events_url,omitempty"` + Site_admin bool `json:"site_admin,omitempty"` + Url string `json:"url,omitempty"` + Avatar_url string `json:"avatar_url,omitempty"` + Gists_url string `json:"gists_url,omitempty"` + Organizations_url string `json:"organizations_url,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Html_url string `json:"html_url,omitempty"` + Login string `json:"login"` + Subscriptions_url string `json:"subscriptions_url,omitempty"` + Starred_url string `json:"starred_url,omitempty"` + Gravatar_id string `json:"gravatar_id,omitempty"` + Id int `json:"id"` + Deleted bool `json:"deleted,omitempty"` + Node_id string `json:"node_id,omitempty"` + Email string `json:"email,omitempty"` + Events_url string `json:"events_url,omitempty"` + Followers_url string `json:"followers_url,omitempty"` + Repos_url string `json:"repos_url,omitempty"` + Following_url string `json:"following_url,omitempty"` + Name string `json:"name,omitempty"` + TypeField string `json:"type,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Billable map[string]interface{} `json:"billable"` + Run_duration_ms int `json:"run_duration_ms,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Changes map[string]interface{} `json:"changes"` + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + Target_type string `json:"target_type"` + Action string `json:"action"` + Account map[string]interface{} `json:"account"` + 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,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 { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Output map[string]interface{} `json:"output"` + Html_url string `json:"html_url"` + Started_at string `json:"started_at"` + External_id string `json:"external_id"` + Name string `json:"name"` // The name of the check. + Completed_at string `json:"completed_at"` + Url string `json:"url"` + Details_url string `json:"details_url"` + 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. + 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 + Head_sha string `json:"head_sha"` // The SHA of the commit that is being checked. + Pull_requests []GeneratedType `json:"pull_requests"` + Conclusion string `json:"conclusion"` + Node_id string `json:"node_id"` + Id int `json:"id"` // The id of the check. + Status string `json:"status"` // The phase of the lifecycle that the check is currently in. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Percentile float64 `json:"percentile,omitempty"` + Percentage float64 `json:"percentage,omitempty"` +} + +// 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 { + Forks_url string `json:"forks_url,omitempty"` + Git_push_url string `json:"git_push_url,omitempty"` + Id string `json:"id,omitempty"` + Comments_enabled bool `json:"comments_enabled,omitempty"` + Owner GeneratedType `json:"owner,omitempty"` // A GitHub user. + Comments int `json:"comments,omitempty"` + Created_at string `json:"created_at,omitempty"` + Forks []map[string]interface{} `json:"forks,omitempty"` + Node_id string `json:"node_id,omitempty"` + Commits_url string `json:"commits_url,omitempty"` + History []GeneratedType `json:"history,omitempty"` + Files map[string]interface{} `json:"files,omitempty"` + Url string `json:"url,omitempty"` + Description string `json:"description,omitempty"` + Html_url string `json:"html_url,omitempty"` + Comments_url string `json:"comments_url,omitempty"` + Updated_at string `json:"updated_at,omitempty"` + Fork_of map[string]interface{} `json:"fork_of,omitempty"` // Gist + Git_pull_url string `json:"git_pull_url,omitempty"` + Public bool `json:"public,omitempty"` + User string `json:"user,omitempty"` + Truncated bool `json:"truncated,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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 { + Start_line float64 `json:"start_line"` // Line number at which the secret starts 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. + Commit_sha string `json:"commit_sha"` // SHA-1 hash ID of the associated commit + Page_url string `json:"page_url"` // The GitHub URL to get the associated wiki page + 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 + Commit_url string `json:"commit_url"` // The GitHub URL to get the associated wiki commit + 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. + End_line float64 `json:"end_line"` // Line number at which the secret ends in the file +} + +// Integration represents the Integration schema from the OpenAPI specification +type Integration struct { + Created_at string `json:"created_at"` + Owner interface{} `json:"owner"` + 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 + Description string `json:"description"` + External_url string `json:"external_url"` + Name string `json:"name"` // The name of the GitHub app + 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. + Html_url string `json:"html_url"` + 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. + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Client_id string `json:"client_id,omitempty"` +} + +// 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,omitempty"` // 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 { + Actor_type string `json:"actor_type"` // The type of actor that can bypass a ruleset. + 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. +} + +// 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 { + 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. + 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 { + Sha string `json:"sha"` + Path string `json:"path"` + Ref string `json:"ref,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Count int `json:"count"` + Referrer string `json:"referrer"` + Uniques int `json:"uniques"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Description string `json:"description"` // The repository's current description. + 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)." + Master_branch string `json:"master_branch"` // The name of the repository's default branch (usually `main`). + 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. + Ref string `json:"ref"` // The [`git ref`](https://docs.github.com/rest/git/refs#get-a-reference) resource. + Pusher_type string `json:"pusher_type"` // The pusher type for the event. Can be either `user` or a deploy key. + 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. +} + +// Authorization represents the Authorization schema from the OpenAPI specification +type Authorization struct { + Expires_at string `json:"expires_at"` + Note_url string `json:"note_url"` + App map[string]interface{} `json:"app"` + Id int64 `json:"id"` + Token string `json:"token"` + Url string `json:"url"` + Fingerprint string `json:"fingerprint"` + Hashed_token string `json:"hashed_token"` + Installation GeneratedType `json:"installation,omitempty"` + Note string `json:"note"` + User GeneratedType `json:"user,omitempty"` // A GitHub user. + Token_last_eight string `json:"token_last_eight"` + Updated_at string `json:"updated_at"` + Created_at string `json:"created_at"` + 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 { + Key_id string `json:"key_id"` + Revoked bool `json:"revoked"` + Created_at string `json:"created_at"` + Primary_key_id int `json:"primary_key_id"` + Can_sign bool `json:"can_sign"` + Can_certify bool `json:"can_certify"` + Id int64 `json:"id"` + Subkeys []map[string]interface{} `json:"subkeys"` + Can_encrypt_storage bool `json:"can_encrypt_storage"` + Public_key string `json:"public_key"` + Emails []map[string]interface{} `json:"emails"` + Can_encrypt_comms bool `json:"can_encrypt_comms"` + Expires_at string `json:"expires_at"` + Name string `json:"name,omitempty"` + Raw_key string `json:"raw_key"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Total_active_caches_count int `json:"total_active_caches_count"` // The count of active caches across all repositories of an enterprise or an organization. + 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. +} + +// 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. + 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. +} + +// Page represents the Page schema from the OpenAPI specification +type Page struct { + Build_type string `json:"build_type,omitempty"` // The process in which the Page will be built. + Https_enforced bool `json:"https_enforced,omitempty"` // Whether https is enabled on the domain + Pending_domain_unverified_at string `json:"pending_domain_unverified_at,omitempty"` // The timestamp when a pending domain becomes unverified. + Protected_domain_state string `json:"protected_domain_state,omitempty"` // The state if the domain is verified + Custom_404 bool `json:"custom_404"` // Whether the Page has a custom 404 page. + Source GeneratedType `json:"source,omitempty"` + 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"` + 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. + Url string `json:"url"` // The API address for accessing this Page resource. +} + +// 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 { + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Cards_url string `json:"cards_url"` + 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"` +} + +// Blob represents the Blob schema from the OpenAPI specification +type Blob struct { + Content string `json:"content"` + Encoding string `json:"encoding"` + 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"` +} + +// 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 { + 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 { + 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`. +} + +// 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 { + Most_recent_instance GeneratedType `json:"most_recent_instance"` + Updated_at string `json:"updated_at,omitempty"` // The time that the alert was last updated 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. + State string `json:"state"` // State of a code scanning alert. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Number int `json:"number"` // The security alert number. + 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"` + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Tool GeneratedType `json:"tool"` + Dismissed_reason string `json:"dismissed_reason"` // **Required when the state is dismissed.** The reason for dismissing or closing the alert. + 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. + 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`. + 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`. +} + +// 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. + Repository GeneratedType `json:"repository"` // Full Repository + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + Completed_at string `json:"completed_at,omitempty"` // Completion time of the last export operation +} + +// Issue represents the Issue schema from the OpenAPI specification +type Issue struct { + Repository_url string `json:"repository_url"` + Active_lock_reason string `json:"active_lock_reason,omitempty"` + 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"` + State_reason string `json:"state_reason,omitempty"` // The reason for the current state + Body string `json:"body,omitempty"` // Contents of the issue + Title string `json:"title"` // Title of the issue + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Id int64 `json:"id"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Assignees []GeneratedType `json:"assignees,omitempty"` + Url string `json:"url"` // URL for the issue + Body_html string `json:"body_html,omitempty"` + Reactions GeneratedType `json:"reactions,omitempty"` + Node_id string `json:"node_id"` + Comments int `json:"comments"` + Labels_url string `json:"labels_url"` + Html_url string `json:"html_url"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Created_at string `json:"created_at"` + User GeneratedType `json:"user"` // A GitHub user. + Events_url string `json:"events_url"` + Updated_at string `json:"updated_at"` + Closed_at string `json:"closed_at"` + Closed_by GeneratedType `json:"closed_by,omitempty"` // A GitHub user. + Timeline_url string `json:"timeline_url,omitempty"` + Body_text string `json:"body_text,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. + Comments_url string `json:"comments_url"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Sub_issues_summary GeneratedType `json:"sub_issues_summary,omitempty"` + Repository Repository `json:"repository,omitempty"` // A repository on GitHub. + Author_association string `json:"author_association"` // How the author is associated with the repository. + State string `json:"state"` // State of the issue; either 'open' or 'closed' + Draft bool `json:"draft,omitempty"` + Number int `json:"number"` // Number uniquely identifying the issue within its 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,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. +} + +// 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"` +} + +// 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"` + 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)." +} + +// 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 { + Release map[string]interface{} `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)." + 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. +} + +// Milestone represents the Milestone schema from the OpenAPI specification +type Milestone struct { + Created_at string `json:"created_at"` + Title string `json:"title"` // The title of the milestone. + Labels_url string `json:"labels_url"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Html_url string `json:"html_url"` + Number int `json:"number"` // The number of the milestone. + State string `json:"state"` // The state of the milestone. + Url string `json:"url"` + Closed_at string `json:"closed_at"` + Description string `json:"description"` + Due_on string `json:"due_on"` + Updated_at string `json:"updated_at"` + Open_issues int `json:"open_issues"` + Closed_issues int `json:"closed_issues"` + Id int `json:"id"` + Node_id string `json:"node_id"` +} + +// Tag represents the Tag schema from the OpenAPI specification +type Tag struct { + Tarball_url string `json:"tarball_url"` + Zipball_url string `json:"zipball_url"` + Commit map[string]interface{} `json:"commit"` + Name string `json:"name"` + Node_id string `json:"node_id"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Controller_repo GeneratedType `json:"controller_repo"` // A GitHub repository. + 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. + 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. + Query_language string `json:"query_language"` // The language targeted by the CodeQL query + Query_pack_url string `json:"query_pack_url"` // The download url for the query pack. + 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. + Status string `json:"status"` + 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. + 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. + Scanned_repositories []map[string]interface{} `json:"scanned_repositories,omitempty"` + Id int `json:"id"` // The ID of 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. + Actor GeneratedType `json:"actor"` // A GitHub user. +} + +// License represents the License schema from the OpenAPI specification +type License struct { + Name string `json:"name"` + Spdx_id string `json:"spdx_id"` + Description string `json:"description"` + Featured bool `json:"featured"` + Url string `json:"url"` + Conditions []string `json:"conditions"` + Implementation string `json:"implementation"` + Key string `json:"key"` + Permissions []string `json:"permissions"` + Body string `json:"body"` + Node_id string `json:"node_id"` + Html_url string `json:"html_url"` + Limitations []string `json:"limitations"` +} + +// Deployment represents the Deployment schema from the OpenAPI specification +type Deployment struct { + Node_id string `json:"node_id"` + Payload interface{} `json:"payload"` + Repository_url string `json:"repository_url"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Description string `json:"description"` + Id int64 `json:"id"` // Unique identifier of the deployment + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Original_environment string `json:"original_environment,omitempty"` + Production_environment bool `json:"production_environment,omitempty"` // Specifies if the given environment is one that end-users directly interact with. Default: false. + 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. + Ref string `json:"ref"` // The ref to deploy. This can be a branch, tag, or sha. + Sha string `json:"sha"` + Statuses_url string `json:"statuses_url"` + Created_at string `json:"created_at"` + Environment string `json:"environment"` // Name for the target deployment environment. + Task string `json:"task"` // Parameter to specify a task to execute + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Marketplace_purchase Webhooksmarketplacepurchase `json:"marketplace_purchase"` + 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. + Previous_marketplace_purchase map[string]interface{} `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"` +} + +// 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 { + Parameters map[string]interface{} `json:"parameters,omitempty"` + TypeField string `json:"type"` +} + +// 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 { + Content map[string]interface{} `json:"content"` + Commit map[string]interface{} `json:"commit"` +} + +// 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_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. + Rule GeneratedType `json:"rule"` + Tool GeneratedType `json:"tool"` + Repository GeneratedType `json:"repository"` // A GitHub repository. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + 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`. + State string `json:"state"` // State of a code scanning alert. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Most_recent_instance GeneratedType `json:"most_recent_instance"` + 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. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + 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`. +} + +// 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 { + Creator GeneratedType `json:"creator,omitempty"` // A GitHub user. + Project_node_id string `json:"project_node_id,omitempty"` + Id float64 `json:"id"` + Node_id string `json:"node_id"` + Status string `json:"status,omitempty"` + Target_date string `json:"target_date,omitempty"` + Updated_at string `json:"updated_at"` + Body string `json:"body,omitempty"` // Body of the status update + Created_at string `json:"created_at"` + Start_date string `json:"start_date,omitempty"` +} + +// 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 { + Actor GeneratedType `json:"actor"` // A GitHub user. + Commit_id string `json:"commit_id"` + Created_at string `json:"created_at"` + Node_id string `json:"node_id"` + Url string `json:"url"` + Commit_url string `json:"commit_url"` + Id int `json:"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. + Project_card map[string]interface{} `json:"project_card,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"` // 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Is_base64_encoded bool `json:"is_base64_encoded,omitempty"` // A boolean value representing whether or not alert is base64 encoded + Number int `json:"number,omitempty"` // The security alert number. + Push_protection_bypassed_by GeneratedType `json:"push_protection_bypassed_by,omitempty"` // A GitHub user. + Publicly_leaked bool `json:"publicly_leaked,omitempty"` // Whether the detected secret was publicly leaked. + 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_at string `json:"resolved_at,omitempty"` // The time that the alert was resolved in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + 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)." + Validity string `json:"validity,omitempty"` // The token status as of the latest validity check. + Created_at string `json:"created_at,omitempty"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + Push_protection_bypassed bool `json:"push_protection_bypassed,omitempty"` // Whether push protection was bypassed for the detected secret. + State string `json:"state,omitempty"` // Sets the state of the secret scanning alert. You must provide `resolution` when you set the state to `resolved`. + Html_url string `json:"html_url,omitempty"` // The GitHub URL of the alert resource. + Resolved_by GeneratedType `json:"resolved_by,omitempty"` // A GitHub user. + Url string `json:"url,omitempty"` // The REST API URL of the alert resource. + Locations_url string `json:"locations_url,omitempty"` // The REST API URL of the code locations for this alert. + Push_protection_bypass_request_reviewer GeneratedType `json:"push_protection_bypass_request_reviewer,omitempty"` // A GitHub user. + Secret string `json:"secret,omitempty"` // The secret that was detected. + 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. + 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_html_url string `json:"push_protection_bypass_request_html_url,omitempty"` // The URL to a push protection bypass request. + Push_protection_bypass_request_reviewer_comment string `json:"push_protection_bypass_request_reviewer_comment,omitempty"` // An optional comment when reviewing a push protection bypass. + 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. + 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_comment string `json:"push_protection_bypass_request_comment,omitempty"` // An optional comment when requesting a push protection bypass. + Secret_type string `json:"secret_type,omitempty"` // The type of secret that secret scanning detected. + Resolution string `json:"resolution,omitempty"` // **Required when the `state` is `resolved`.** The reason for resolving the alert. + Resolution_comment string `json:"resolution_comment,omitempty"` // An optional comment to resolve an alert. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Total_paid_gigabytes_bandwidth_used int `json:"total_paid_gigabytes_bandwidth_used"` // Total paid storage space (GB) for GitHuub Packages. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Subscriptions_url string `json:"subscriptions_url"` + Login string `json:"login"` + Node_id string `json:"node_id"` + Followers_url string `json:"followers_url"` + Gists_url string `json:"gists_url"` + Organizations_url string `json:"organizations_url"` + Starred_at string `json:"starred_at,omitempty"` + Avatar_url string `json:"avatar_url"` + Email string `json:"email,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Html_url string `json:"html_url"` + TypeField string `json:"type"` + Id int64 `json:"id"` + Repos_url string `json:"repos_url"` + Starred_url string `json:"starred_url"` + Following_url string `json:"following_url"` + Gravatar_id string `json:"gravatar_id"` + Name string `json:"name,omitempty"` + Url string `json:"url"` + Events_url string `json:"events_url"` + Received_events_url string `json:"received_events_url"` + Site_admin bool `json:"site_admin"` +} + +// 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 { + User GeneratedType `json:"user"` // Collaborator + Permission string `json:"permission"` + Role_name string `json:"role_name"` +} + +// 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"` + 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. +} + +// 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 { + Vulnerable_version_range string `json:"vulnerable_version_range"` // The range of the package versions affected by the vulnerability. + 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. +} + +// 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"` // 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. +} + +// Reaction represents the Reaction schema from the OpenAPI specification +type Reaction struct { + Content string `json:"content"` // The reaction to use + Created_at string `json:"created_at"` + Id int `json:"id"` + Node_id string `json:"node_id"` + 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,omitempty"` + Created_at string `json:"created_at,omitempty"` + Enabled bool `json:"enabled,omitempty"` + Id int `json:"id,omitempty"` + Pattern string `json:"pattern"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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_at string `json:"dismissed_at"` // The time that the alert was dismissed in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + 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`. + Html_url string `json:"html_url"` // The GitHub URL of the alert resource. + Url string `json:"url"` // The REST API URL of the alert resource. + Dismissed_reason string `json:"dismissed_reason"` // The reason that the alert was dismissed. + Created_at string `json:"created_at"` // The time that the alert was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + 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`. + Number int `json:"number"` // The security alert number. + State string `json:"state"` // The state of the Dependabot alert. + Dismissed_comment string `json:"dismissed_comment"` // An optional comment associated with the alert's dismissal. + Security_advisory GeneratedType `json:"security_advisory"` // Details for the GitHub Security Advisory. + Dismissed_by GeneratedType `json:"dismissed_by"` // A GitHub user. + Dependency map[string]interface{} `json:"dependency"` // Details for the vulnerable dependency. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + Url string `json:"url,omitempty"` + Created_at string `json:"created_at,omitempty"` +} + +// 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 { + 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 { + Limit int `json:"limit"` + Remaining int `json:"remaining"` + Reset int `json:"reset"` + Used int `json:"used"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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`. + 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 { + Comment string `json:"comment"` // Comment associated with the pending deployment protection rule. **Required when state is not provided.** + 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 { + Changes int `json:"changes"` + Contents_url string `json:"contents_url"` + Deletions int `json:"deletions"` + Previous_filename string `json:"previous_filename,omitempty"` + Raw_url string `json:"raw_url"` + Sha string `json:"sha"` + Status string `json:"status"` + Blob_url string `json:"blob_url"` + Filename string `json:"filename"` + Patch string `json:"patch,omitempty"` + Additions int `json:"additions"` +} + +// 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"` +} + +// Webhooksreviewcomment represents the Webhooksreviewcomment schema from the OpenAPI specification +type Webhooksreviewcomment struct { + Side string `json:"side"` // The side of the first line of the range for a multi-line comment. + Html_url string `json:"html_url"` // HTML URL for the pull request review comment. + Updated_at string `json:"updated_at"` + Path string `json:"path"` // The relative path of the file to which the comment applies. + Start_side string `json:"start_side"` // The side of the first line of the range for a multi-line comment. + User map[string]interface{} `json:"user"` + 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_start_line int `json:"original_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. + Start_line int `json:"start_line"` // The first line of the range for a multi-line comment. + Url string `json:"url"` // URL for the pull request review comment + Author_association string `json:"author_association"` // How the author is associated with the repository. + Node_id string `json:"node_id"` // The node ID of the pull request review 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 + Original_position int `json:"original_position"` // The index of the original line in the diff to which the comment applies. + Original_commit_id string `json:"original_commit_id"` // The SHA of the original commit 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. + Body string `json:"body"` // The text of the comment. + Created_at string `json:"created_at"` + Links map[string]interface{} `json:"_links"` + Diff_hunk string `json:"diff_hunk"` // The diff of the line that the comment refers to. + Id int `json:"id"` // The ID of the pull request review comment. + Commit_id string `json:"commit_id"` // The SHA of the commit to which the comment applies. + In_reply_to_id int `json:"in_reply_to_id,omitempty"` // The comment ID to reply to. + Pull_request_review_id int `json:"pull_request_review_id"` // The ID of the pull request review to which the comment belongs. + Pull_request_url string `json:"pull_request_url"` // URL for the pull request that the review comment belongs to. + Reactions map[string]interface{} `json:"reactions"` +} + +// 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 { + Provider string `json:"provider"` + Url string `json:"url"` +} + +// Dependency represents the Dependency schema from the OpenAPI specification +type Dependency struct { + Package_url string `json:"package_url,omitempty"` // Package-url (PURL) of dependency. See https://github.com/package-url/purl-spec for more details. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` + Id int `json:"id"` + Monthly_price_in_cents int `json:"monthly_price_in_cents"` + Number int `json:"number"` + State string `json:"state"` + Accounts_url string `json:"accounts_url"` + Has_free_trial bool `json:"has_free_trial"` + Name string `json:"name"` + Price_model string `json:"price_model"` + Unit_name string `json:"unit_name"` + Yearly_price_in_cents int `json:"yearly_price_in_cents"` + Bullets []string `json:"bullets"` + Description string `json:"description"` +} + +// 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"` // A GitHub user. + Action string `json:"action"` +} + +// 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Total int `json:"total"` + Completed int `json:"completed"` + Percent_completed int `json:"percent_completed"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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 + Message string `json:"message"` // Message describing the purpose of the commit +} + +// 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"` + 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"` // 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 { + 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 { + TypeField string `json:"type"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Rules []GeneratedType `json:"rules,omitempty"` + Source_type string `json:"source_type,omitempty"` // The type of the source of the ruleset + Conditions interface{} `json:"conditions,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. + 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). + Updated_at string `json:"updated_at,omitempty"` + Bypass_actors []GeneratedType `json:"bypass_actors,omitempty"` // The actors that can bypass the rules in this ruleset + Id int `json:"id"` // The ID of the ruleset + Name string `json:"name"` // The name of the ruleset + Source string `json:"source"` // The name of the source + Target string `json:"target,omitempty"` // The target of the ruleset + Links map[string]interface{} `json:"_links,omitempty"` + Created_at string `json:"created_at,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_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 { + Name string `json:"name"` + Git_tags_url string `json:"git_tags_url"` + Fork bool `json:"fork"` + Url string `json:"url"` + Has_projects bool `json:"has_projects"` + Updated_at string `json:"updated_at"` + Clone_url string `json:"clone_url"` + Archived bool `json:"archived"` + Forks_url string `json:"forks_url"` + Trees_url string `json:"trees_url"` + Has_issues bool `json:"has_issues"` + Statuses_url string `json:"statuses_url"` + Web_commit_signoff_required bool `json:"web_commit_signoff_required,omitempty"` + Contributors_url string `json:"contributors_url"` + Compare_url string `json:"compare_url"` + Has_wiki bool `json:"has_wiki"` + Private bool `json:"private"` + Git_commits_url string `json:"git_commits_url"` + Issue_events_url string `json:"issue_events_url"` + Visibility string `json:"visibility,omitempty"` // The repository visibility: public, private, or internal. + Collaborators_url string `json:"collaborators_url"` + Homepage string `json:"homepage"` + Tags_url string `json:"tags_url"` + Commits_url string `json:"commits_url"` + Language string `json:"language"` + Node_id string `json:"node_id"` + Delete_branch_on_merge bool `json:"delete_branch_on_merge,omitempty"` + Issues_url string `json:"issues_url"` + Mirror_url string `json:"mirror_url"` + License GeneratedType `json:"license"` // License Simple + Allow_merge_commit bool `json:"allow_merge_commit,omitempty"` + Has_pages bool `json:"has_pages"` + Assignees_url string `json:"assignees_url"` + Issue_comment_url string `json:"issue_comment_url"` + Id int `json:"id"` + Allow_forking bool `json:"allow_forking,omitempty"` + Comments_url string `json:"comments_url"` + Subscribers_url string `json:"subscribers_url"` + Forks int `json:"forks"` + Default_branch string `json:"default_branch"` + Open_issues int `json:"open_issues"` + Score float64 `json:"score"` + Deployments_url string `json:"deployments_url"` + Full_name string `json:"full_name"` + Labels_url string `json:"labels_url"` + Svn_url string `json:"svn_url"` + Subscription_url string `json:"subscription_url"` + Ssh_url string `json:"ssh_url"` + Keys_url string `json:"keys_url"` + Stargazers_url string `json:"stargazers_url"` + Stargazers_count int `json:"stargazers_count"` + Permissions map[string]interface{} `json:"permissions,omitempty"` + Languages_url string `json:"languages_url"` + Notifications_url string `json:"notifications_url"` + Archive_url string `json:"archive_url"` + Blobs_url string `json:"blobs_url"` + Pushed_at string `json:"pushed_at"` + Created_at string `json:"created_at"` + Temp_clone_token string `json:"temp_clone_token,omitempty"` + Watchers int `json:"watchers"` + Owner GeneratedType `json:"owner"` // A GitHub user. + Downloads_url string `json:"downloads_url"` + Size int `json:"size"` + Contents_url string `json:"contents_url"` + Merges_url string `json:"merges_url"` + Topics []string `json:"topics,omitempty"` + Disabled bool `json:"disabled"` // Returns whether or not this repository disabled. + Allow_squash_merge bool `json:"allow_squash_merge,omitempty"` + Branches_url string `json:"branches_url"` + Has_downloads bool `json:"has_downloads"` + Git_refs_url string `json:"git_refs_url"` + Hooks_url string `json:"hooks_url"` + Is_template bool `json:"is_template,omitempty"` + Pulls_url string `json:"pulls_url"` + Description string `json:"description"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Master_branch string `json:"master_branch,omitempty"` + Has_discussions bool `json:"has_discussions,omitempty"` + Allow_rebase_merge bool `json:"allow_rebase_merge,omitempty"` + Open_issues_count int `json:"open_issues_count"` + Events_url string `json:"events_url"` + Forks_count int `json:"forks_count"` + Html_url string `json:"html_url"` + Watchers_count int `json:"watchers_count"` + Git_url string `json:"git_url"` + Releases_url string `json:"releases_url"` + Teams_url string `json:"teams_url"` + Allow_auto_merge bool `json:"allow_auto_merge,omitempty"` + Milestones_url string `json:"milestones_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Name string `json:"name,omitempty"` // The name of the tool used to generate the code scanning analysis. + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + In_reply_to_id int `json:"in_reply_to_id,omitempty"` + Subject_type string `json:"subject_type,omitempty"` // The level at which the comment is targeted, can be a diff line or a file. + Original_start_line int `json:"original_start_line,omitempty"` // The original first line of the range for a multi-line comment. + Body_text string `json:"body_text,omitempty"` + Html_url string `json:"html_url"` + Position int `json:"position"` + Id int64 `json:"id"` + Diff_hunk string `json:"diff_hunk"` + Original_position int `json:"original_position"` + Side string `json:"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"` + Updated_at string `json:"updated_at"` + Start_side string `json:"start_side,omitempty"` // The side of the first line of the range for a multi-line comment. + Links map[string]interface{} `json:"_links"` + Body string `json:"body"` + Pull_request_url string `json:"pull_request_url"` + Original_commit_id string `json:"original_commit_id"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Path string `json:"path"` + Commit_id string `json:"commit_id"` + Node_id string `json:"node_id"` + Start_line int `json:"start_line,omitempty"` // The first line of the range for a multi-line comment. + Url string `json:"url"` + Created_at string `json:"created_at"` + 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 + Reactions GeneratedType `json:"reactions,omitempty"` + User GeneratedType `json:"user"` // A GitHub user. + 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 + Body_html string `json:"body_html,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Marketplace_purchase map[string]interface{} `json:"marketplace_purchase"` + Previous_marketplace_purchase Webhookspreviousmarketplacepurchase `json:"previous_marketplace_purchase,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,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. + Effective_date string `json:"effective_date"` + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. + Action string `json:"action"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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`. + 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. +} + +// 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)." + 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 { + 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 { + 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. + Requested_action map[string]interface{} `json:"requested_action,omitempty"` // The action requested by the user. +} + +// Webhooksrule represents the Webhooksrule schema from the OpenAPI specification +type Webhooksrule struct { + Required_conversation_resolution_level string `json:"required_conversation_resolution_level"` + Admin_enforced bool `json:"admin_enforced"` + Repository_id int `json:"repository_id"` + 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 + Strict_required_status_checks_policy bool `json:"strict_required_status_checks_policy"` + Required_status_checks []string `json:"required_status_checks"` + 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. + Create_protected bool `json:"create_protected,omitempty"` + Ignore_approvals_from_contributors bool `json:"ignore_approvals_from_contributors"` + Allow_deletions_enforcement_level string `json:"allow_deletions_enforcement_level"` + Id int `json:"id"` + Name string `json:"name"` + Pull_request_reviews_enforcement_level string `json:"pull_request_reviews_enforcement_level"` + 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. + Required_approving_review_count int `json:"required_approving_review_count"` + Authorized_actor_names []string `json:"authorized_actor_names"` + Required_status_checks_enforcement_level string `json:"required_status_checks_enforcement_level"` + Dismiss_stale_reviews_on_push bool `json:"dismiss_stale_reviews_on_push"` + Signature_requirement_enforcement_level string `json:"signature_requirement_enforcement_level"` + Allow_force_pushes_enforcement_level string `json:"allow_force_pushes_enforcement_level"` + Merge_queue_enforcement_level string `json:"merge_queue_enforcement_level"` + Authorized_actors_only bool `json:"authorized_actors_only"` + Authorized_dismissal_actors_only bool `json:"authorized_dismissal_actors_only"` + Linear_history_requirement_enforcement_level string `json:"linear_history_requirement_enforcement_level"` + Created_at string `json:"created_at"` + Require_code_owner_review bool `json:"require_code_owner_review"` + Required_deployments_enforcement_level string `json:"required_deployments_enforcement_level"` + Updated_at string `json:"updated_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Repository_count int `json:"repository_count"` // The total number of repositories that were skipped for this reason. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Repos_url string `json:"repos_url"` + TypeField string `json:"type"` + Id int `json:"id"` + Url string `json:"url"` + Inherited_from []GeneratedType `json:"inherited_from,omitempty"` // Team the user has gotten the role through + Name string `json:"name,omitempty"` + Organizations_url string `json:"organizations_url"` + Starred_at string `json:"starred_at,omitempty"` + Site_admin bool `json:"site_admin"` + Html_url string `json:"html_url"` + Following_url string `json:"following_url"` + Gravatar_id string `json:"gravatar_id"` + Received_events_url string `json:"received_events_url"` + Node_id string `json:"node_id"` + Email string `json:"email,omitempty"` + User_view_type string `json:"user_view_type,omitempty"` + Assignment string `json:"assignment,omitempty"` // Determines if the user has a direct, indirect, or mixed relationship to a role + Events_url string `json:"events_url"` + Followers_url string `json:"followers_url"` + Gists_url string `json:"gists_url"` + Login string `json:"login"` + Avatar_url string `json:"avatar_url"` + Starred_url string `json:"starred_url"` + Subscriptions_url string `json:"subscriptions_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Environment_url string `json:"environment_url,omitempty"` // The URL for accessing your environment. + Creator GeneratedType `json:"creator"` // A GitHub user. + 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. + Url string `json:"url"` + Repository_url string `json:"repository_url"` + State string `json:"state"` // The state of the status. + Updated_at string `json:"updated_at"` + Deployment_url string `json:"deployment_url"` + Environment string `json:"environment,omitempty"` // The environment of the deployment that the status is for. + Node_id string `json:"node_id"` + Log_url string `json:"log_url,omitempty"` // The URL to associate with this status. + Target_url string `json:"target_url"` // Closing down notice: the URL to associate with this status. + Created_at string `json:"created_at"` + Description string `json:"description"` // A short description of the status. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Sub_issue Issue `json:"sub_issue"` // Issues are a great way to keep track of tasks, enhancements, and bugs for your projects. + Sender GeneratedType `json:"sender,omitempty"` // A GitHub user. + 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_repo Repository `json:"parent_issue_repo"` // A repository on GitHub. + 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"` + 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. + 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)." +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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)." + 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 { + Merged bool `json:"merged"` + Message string `json:"message"` + Sha string `json:"sha"` +} + +// 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 { + Errors []map[string]interface{} `json:"errors,omitempty"` + Message string `json:"message"` + Documentation_url string `json:"documentation_url"` +} + +// 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 { + 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"` + 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"` + Due_on string `json:"due_on"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Url string `json:"url"` + State string `json:"state"` // The state of the milestone. + Title string `json:"title"` // The title of the milestone. + Closed_issues int `json:"closed_issues"` + Labels_url string `json:"labels_url"` + Number int `json:"number"` // The number of the milestone. + Updated_at string `json:"updated_at"` + Id int `json:"id"` + Open_issues int `json:"open_issues"` + Created_at string `json:"created_at"` + Description string `json:"description"` + Html_url string `json:"html_url"` + Closed_at string `json:"closed_at"` +} + +// Verification represents the Verification schema from the OpenAPI specification +type Verification struct { + Verified_at string `json:"verified_at"` + Payload string `json:"payload"` + Reason string `json:"reason"` + Signature string `json:"signature"` + Verified bool `json:"verified"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Organization_custom_roles string `json:"organization_custom_roles,omitempty"` // The level of permission to grant the access token for custom repository roles management. + Metadata string `json:"metadata,omitempty"` // The level of permission to grant the access token to search repositories, list collaborators, and access repository metadata. + 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. + 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. + 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. + Checks string `json:"checks,omitempty"` // The level of permission to grant the access token for checks on code. + Packages string `json:"packages,omitempty"` // The level of permission to grant the access token for packages published to GitHub Packages. + Team_discussions string `json:"team_discussions,omitempty"` // The level of permission to grant the access token to manage team discussions and related comments. + Issues string `json:"issues,omitempty"` // The level of permission to grant the access token for issues and related comments, assignees, labels, and milestones. + Contents string `json:"contents,omitempty"` // The level of permission to grant the access token for repository contents, commits, branches, downloads, releases, and merges. + Codespaces string `json:"codespaces,omitempty"` // The level of permission to grant the access token to create, edit, delete, and list Codespaces. + Organization_administration string `json:"organization_administration,omitempty"` // The level of permission to grant the access token to manage access to an organization. + Workflows string `json:"workflows,omitempty"` // The level of permission to grant the access token to update GitHub Actions workflow files. + Starring string `json:"starring,omitempty"` // The level of permission to grant the access token to list and manage repositories a user is starring. + 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. + 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. + Members string `json:"members,omitempty"` // The level of permission to grant the access token for organization teams and members. + 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. + 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. + Administration string `json:"administration,omitempty"` // The level of permission to grant the access token for repository creation, deletion, settings, teams, and collaborators creation. + 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. + 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. + Single_file string `json:"single_file,omitempty"` // The level of permission to grant the access token to manage just a single file. + 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. + 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_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. + Repository_projects string `json:"repository_projects,omitempty"` // The level of permission to grant the access token to manage repository projects, columns, and cards. + Actions string `json:"actions,omitempty"` // The level of permission to grant the access token for GitHub Actions workflows, workflow runs, and artifacts. + 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. + Environments string `json:"environments,omitempty"` // The level of permission to grant the access token for managing repository environments. + 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. + Deployments string `json:"deployments,omitempty"` // The level of permission to grant the access token for deployments and deployment statuses. + Profile string `json:"profile,omitempty"` // The level of permission to grant the access token to manage the profile settings belonging to a user. + Organization_packages string `json:"organization_packages,omitempty"` // The level of permission to grant the access token for organization packages published to GitHub Packages. + Git_ssh_keys string `json:"git_ssh_keys,omitempty"` // The level of permission to grant the access token to manage git SSH keys. + 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. + Statuses string `json:"statuses,omitempty"` // The level of permission to grant the access token for commit statuses. + 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_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. + Dependabot_secrets string `json:"dependabot_secrets,omitempty"` // The level of permission to grant the access token to manage Dependabot secrets. + 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. + Organization_custom_properties string `json:"organization_custom_properties,omitempty"` // The level of permission to grant the access token for custom property management. + Vulnerability_alerts string `json:"vulnerability_alerts,omitempty"` // The level of permission to grant the access token to manage Dependabot alerts. + Organization_secrets string `json:"organization_secrets,omitempty"` // The level of permission to grant the access token to manage organization secrets. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Url string `json:"url"` // The URL to the workflow run. + Status string `json:"status"` + Head_sha string `json:"head_sha"` // The SHA of the head commit that points to the version of the workflow being run. + 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. + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Event string `json:"event"` + Html_url string `json:"html_url"` + Head_repository_id int `json:"head_repository_id,omitempty"` + Run_started_at string `json:"run_started_at,omitempty"` // The start time of the latest run. Resets on re-run. + Previous_attempt_url string `json:"previous_attempt_url,omitempty"` // The URL to the previous attempted run of this workflow, if one exists. + Head_commit GeneratedType `json:"head_commit"` // A commit. + Triggering_actor GeneratedType `json:"triggering_actor,omitempty"` // A GitHub user. + Logs_url string `json:"logs_url"` // The URL to download the logs for the workflow run. + Head_repository GeneratedType `json:"head_repository"` // Minimal Repository + Check_suite_node_id string `json:"check_suite_node_id,omitempty"` // The node ID of the associated check suite. + Workflow_id int `json:"workflow_id"` // The ID of the parent workflow. + Referenced_workflows []GeneratedType `json:"referenced_workflows,omitempty"` + Workflow_url string `json:"workflow_url"` // The URL to the workflow. + Check_suite_id int `json:"check_suite_id,omitempty"` // The ID of the associated check suite. + Head_branch string `json:"head_branch"` + Repository GeneratedType `json:"repository"` // Minimal Repository + Run_attempt int `json:"run_attempt,omitempty"` // Attempt number of the run, 1 for first attempt and higher if the workflow was re-run. + Actor GeneratedType `json:"actor,omitempty"` // A GitHub user. + Path string `json:"path"` // The full path of the workflow + Id int `json:"id"` // The ID of the workflow run. + Jobs_url string `json:"jobs_url"` // The URL to the jobs for the workflow run. + Run_number int `json:"run_number"` // The auto incrementing run number for the workflow run. + 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. + Cancel_url string `json:"cancel_url"` // The URL to cancel the workflow run. + Check_suite_url string `json:"check_suite_url"` // The URL to the associated check suite. + Conclusion string `json:"conclusion"` + Created_at string `json:"created_at"` + Name string `json:"name,omitempty"` // The name of the workflow run. + Artifacts_url string `json:"artifacts_url"` // The URL to the artifacts for the workflow run. + Rerun_url string `json:"rerun_url"` // The URL to rerun the workflow run. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + User GeneratedType `json:"user"` // A GitHub user. + Sub_issues_summary map[string]interface{} `json:"sub_issues_summary,omitempty"` + Locked bool `json:"locked"` + State string `json:"state"` + Title string `json:"title"` + Id int64 `json:"id"` + Number int `json:"number"` + Active_lock_reason string `json:"active_lock_reason,omitempty"` + State_reason string `json:"state_reason,omitempty"` + Text_matches []map[string]interface{} `json:"text_matches,omitempty"` + Assignees []GeneratedType `json:"assignees,omitempty"` + Html_url string `json:"html_url"` + Closed_at string `json:"closed_at"` + Draft bool `json:"draft,omitempty"` + Events_url string `json:"events_url"` + Author_association string `json:"author_association"` // How the author is associated with the repository. + Score float64 `json:"score"` + TypeField GeneratedType `json:"type,omitempty"` // The type of issue. + Comments int `json:"comments"` + Body_text string `json:"body_text,omitempty"` + Labels_url string `json:"labels_url"` + Timeline_url string `json:"timeline_url,omitempty"` + Comments_url string `json:"comments_url"` + Updated_at string `json:"updated_at"` + 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. + Reactions GeneratedType `json:"reactions,omitempty"` + Pull_request map[string]interface{} `json:"pull_request,omitempty"` + Labels []map[string]interface{} `json:"labels"` + Repository_url string `json:"repository_url"` + Created_at string `json:"created_at"` + Url string `json:"url"` + Milestone GeneratedType `json:"milestone"` // A collection of related issues and pull requests. + Node_id string `json:"node_id"` + Repository Repository `json:"repository,omitempty"` // A repository on GitHub. + Assignee GeneratedType `json:"assignee"` // A GitHub user. + Body_html string `json:"body_html,omitempty"` + Body string `json:"body,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id"` + Updated_at string `json:"updated_at"` + Column_name string `json:"column_name,omitempty"` + Creator GeneratedType `json:"creator"` // A GitHub user. + Created_at string `json:"created_at"` + Project_url string `json:"project_url"` + Note string `json:"note"` + Project_id string `json:"project_id,omitempty"` + Url string `json:"url"` + Archived bool `json:"archived,omitempty"` // Whether or not the card is archived + Column_url string `json:"column_url"` + Content_url string `json:"content_url,omitempty"` + Id int64 `json:"id"` // The project card's ID +} + +// Import represents the Import schema from the OpenAPI specification +type Import struct { + Authors_url string `json:"authors_url"` + Error_message string `json:"error_message,omitempty"` + Project_choices []map[string]interface{} `json:"project_choices,omitempty"` + Svc_root string `json:"svc_root,omitempty"` + Authors_count int `json:"authors_count,omitempty"` + Message string `json:"message,omitempty"` + Url string `json:"url"` + Html_url string `json:"html_url"` + Large_files_size int `json:"large_files_size,omitempty"` + Commit_count int `json:"commit_count,omitempty"` + Failed_step string `json:"failed_step,omitempty"` + Use_lfs bool `json:"use_lfs,omitempty"` + Vcs_url string `json:"vcs_url"` // The URL of the originating repository. + Tfvc_project string `json:"tfvc_project,omitempty"` + Repository_url string `json:"repository_url"` + Has_large_files bool `json:"has_large_files,omitempty"` + Import_percent int `json:"import_percent,omitempty"` + Large_files_count int `json:"large_files_count,omitempty"` + Svn_root string `json:"svn_root,omitempty"` + Vcs string `json:"vcs"` + Status_text string `json:"status_text,omitempty"` + Status string `json:"status"` + Push_percent int `json:"push_percent,omitempty"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + 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 { + 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. + Milestone Webhooksmilestone `json:"milestone"` // A collection of related issues and pull requests. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` // 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Warning string `json:"warning"` // Warning generated when processing the analysis + Sarif_id string `json:"sarif_id"` // An identifier for the upload. + Results_count int `json:"results_count"` // The total number of results in the analysis. + Url string `json:"url"` // The REST API URL of the analysis resource. + Deletable bool `json:"deletable"` + Id int `json:"id"` // Unique identifier for this analysis. + 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"` // The SHA of the commit to which the analysis you are uploading relates. + Tool GeneratedType `json:"tool"` + Rules_count int `json:"rules_count"` // The total number of rules used in the analysis. + Environment string `json:"environment"` // Identifies the variable values associated with the environment in which this analysis was performed. + Created_at string `json:"created_at"` // The time that the analysis was created in ISO 8601 format: `YYYY-MM-DDTHH:MM:SSZ`. + ErrorField string `json:"error"` + Ref string `json:"ref"` // The Git reference, formatted as `refs/pull//merge`, `refs/pull//head`, `refs/heads/` or simply ``. + 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. +} + +// 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 { + 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. + Ruleset_id int `json:"ruleset_id,omitempty"` // The ID of the ruleset that includes this rule. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + Assignment GeneratedType `json:"assignment"` // A GitHub Classroom assignment + Commit_count int `json:"commit_count"` // Count of student commits. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Actions_caches []map[string]interface{} `json:"actions_caches"` // Array of caches + Total_count int `json:"total_count"` // Total number of caches +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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"` + 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. +} + +// 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)." + 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. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Preferences map[string]interface{} `json:"preferences"` + Repository GeneratedType `json:"repository"` // Minimal Repository +} + +// Webhooksworkflowjobrun represents the Webhooksworkflowjobrun schema from the OpenAPI specification +type Webhooksworkflowjobrun struct { + Environment string `json:"environment"` + Html_url string `json:"html_url"` + Id int `json:"id"` + Name interface{} `json:"name"` + Status string `json:"status"` + Updated_at string `json:"updated_at"` + Conclusion interface{} `json:"conclusion"` + Created_at string `json:"created_at"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Owner GeneratedType `json:"owner,omitempty"` // A GitHub user. + Created_at string `json:"created_at"` + History []interface{} `json:"history,omitempty"` + Id string `json:"id"` + Updated_at string `json:"updated_at"` + Git_push_url string `json:"git_push_url"` + Forks_url string `json:"forks_url"` + Public bool `json:"public"` + Description string `json:"description"` + Forks []interface{} `json:"forks,omitempty"` + Node_id string `json:"node_id"` + Comments_enabled bool `json:"comments_enabled,omitempty"` + Commits_url string `json:"commits_url"` + Files map[string]interface{} `json:"files"` + Truncated bool `json:"truncated,omitempty"` + Git_pull_url string `json:"git_pull_url"` + Comments int `json:"comments"` + User GeneratedType `json:"user"` // A GitHub user. + Html_url string `json:"html_url"` + Url string `json:"url"` + Comments_url string `json:"comments_url"` +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Node_id string `json:"node_id,omitempty"` + Requester GeneratedType `json:"requester"` // A GitHub user. + Account interface{} `json:"account"` + Created_at string `json:"created_at"` + Id int `json:"id"` // Unique identifier of the request installation. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + 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. + 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,omitempty"` + Pull_request map[string]interface{} `json:"pull_request"` + 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. + Sender GeneratedType `json:"sender"` // A GitHub user. +} + +// GeneratedType represents the GeneratedType schema from the OpenAPI specification +type GeneratedType struct { + Title string `json:"title"` // Assignment title. + Invite_link string `json:"invite_link"` // The link that a student can use to accept the assignment. + Passing int `json:"passing"` // The number of students that have passed the assignment. + Max_members int `json:"max_members,omitempty"` // The maximum allowable members per team. + Public_repo bool `json:"public_repo"` // Whether an accepted assignment creates a public repository. + Id int `json:"id"` // Unique identifier of the repository. + Submitted int `json:"submitted"` // The number of students that have submitted 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. + TypeField string `json:"type"` // Whether it's a Group Assignment or Individual Assignment. + Feedback_pull_requests_enabled bool `json:"feedback_pull_requests_enabled"` // Whether feedback pull request will be created on assignment acceptance. + Deadline string `json:"deadline"` // The time at which the assignment is due. + Classroom GeneratedType `json:"classroom"` // A GitHub Classroom classroom + Editor string `json:"editor"` // The selected editor for the assignment. + Invitations_enabled bool `json:"invitations_enabled"` // Whether the invitation link is enabled. Visiting an enabled invitation link will accept the assignment. + Language string `json:"language"` // The programming language used in the assignment. + Slug string `json:"slug"` // Sluggified name of the assignment. + Max_teams int `json:"max_teams,omitempty"` // The maximum allowable teams for the assignment. +} + +// 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 { + Commit_id string `json:"commit_id"` + Commit_url string `json:"commit_url"` + Created_at string `json:"created_at"` + Event string `json:"event"` + Id int `json:"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. + Actor GeneratedType `json:"actor"` // A GitHub user. + Node_id string `json:"node_id"` + Project_card map[string]interface{} `json:"project_card,omitempty"` + Url string `json:"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. + 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. +} + +// Status represents the Status schema from the OpenAPI specification +type Status struct { + State string `json:"state"` + Id int `json:"id"` + Created_at string `json:"created_at"` + Description string `json:"description"` + Node_id string `json:"node_id"` + Target_url string `json:"target_url"` + Updated_at string `json:"updated_at"` + Url string `json:"url"` + Avatar_url string `json:"avatar_url"` + Context string `json:"context"` + Creator GeneratedType `json:"creator"` // A GitHub user. +} diff --git a/MCP/registry.go b/MCP/registry.go new file mode 100644 index 0000000..f26c305 --- /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_dependabot "github.com/github-v3-rest-api/mcp-server/tools/dependabot" + tools_orgs "github.com/github-v3-rest-api/mcp-server/tools/orgs" + tools_repos "github.com/github-v3-rest-api/mcp-server/tools/repos" + tools_code_scanning "github.com/github-v3-rest-api/mcp-server/tools/code_scanning" + tools_actions "github.com/github-v3-rest-api/mcp-server/tools/actions" + tools_users "github.com/github-v3-rest-api/mcp-server/tools/users" + 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_reactions "github.com/github-v3-rest-api/mcp-server/tools/reactions" + tools_classroom "github.com/github-v3-rest-api/mcp-server/tools/classroom" + tools_issues "github.com/github-v3-rest-api/mcp-server/tools/issues" + tools_codespaces "github.com/github-v3-rest-api/mcp-server/tools/codespaces" + tools_copilot "github.com/github-v3-rest-api/mcp-server/tools/copilot" + tools_gists "github.com/github-v3-rest-api/mcp-server/tools/gists" + tools_activity "github.com/github-v3-rest-api/mcp-server/tools/activity" + tools_packages "github.com/github-v3-rest-api/mcp-server/tools/packages" + tools_apps "github.com/github-v3-rest-api/mcp-server/tools/apps" + tools_licenses "github.com/github-v3-rest-api/mcp-server/tools/licenses" + tools_checks "github.com/github-v3-rest-api/mcp-server/tools/checks" + tools_teams "github.com/github-v3-rest-api/mcp-server/tools/teams" + tools_git "github.com/github-v3-rest-api/mcp-server/tools/git" + tools_search "github.com/github-v3-rest-api/mcp-server/tools/search" + tools_meta "github.com/github-v3-rest-api/mcp-server/tools/meta" + tools_pulls "github.com/github-v3-rest-api/mcp-server/tools/pulls" + tools_migrations "github.com/github-v3-rest-api/mcp-server/tools/migrations" + tools_billing "github.com/github-v3-rest-api/mcp-server/tools/billing" + tools_interactions "github.com/github-v3-rest-api/mcp-server/tools/interactions" + tools_security_advisories "github.com/github-v3-rest-api/mcp-server/tools/security_advisories" + tools_secret_scanning "github.com/github-v3-rest-api/mcp-server/tools/secret_scanning" + tools_dependency_graph "github.com/github-v3-rest-api/mcp-server/tools/dependency_graph" + tools_codes_of_conduct "github.com/github-v3-rest-api/mcp-server/tools/codes_of_conduct" + tools_projects "github.com/github-v3-rest-api/mcp-server/tools/projects" + tools_credentials "github.com/github-v3-rest-api/mcp-server/tools/credentials" + tools_hosted_compute "github.com/github-v3-rest-api/mcp-server/tools/hosted_compute" + tools_gitignore "github.com/github-v3-rest-api/mcp-server/tools/gitignore" + tools_rate_limit "github.com/github-v3-rest-api/mcp-server/tools/rate_limit" + tools_campaigns "github.com/github-v3-rest-api/mcp-server/tools/campaigns" + tools_private_registries "github.com/github-v3-rest-api/mcp-server/tools/private_registries" + tools_oidc "github.com/github-v3-rest-api/mcp-server/tools/oidc" +) + +func GetAll(cfg *config.APIConfig) []models.Tool { + return []models.Tool{ + tools_dependabot.CreateDependabot_get_alertTool(cfg), + tools_dependabot.CreateDependabot_update_alertTool(cfg), + tools_orgs.CreateOrgs_list_for_userTool(cfg), + tools_repos.CreateRepos_list_for_orgTool(cfg), + tools_repos.CreateRepos_create_in_orgTool(cfg), + tools_code_scanning.CreateCode_scanning_get_autofixTool(cfg), + tools_code_scanning.CreateCode_scanning_create_autofixTool(cfg), + tools_orgs.CreateOrgs_get_webhook_deliveryTool(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_actions.CreateActions_get_hosted_runners_partner_images_for_orgTool(cfg), + tools_users.CreateUsers_get_by_idTool(cfg), + tools_orgs.CreateOrgs_list_attestations_bulkTool(cfg), + tools_repos.CreateRepos_get_top_pathsTool(cfg), + tools_orgs.CreateOrgs_redeliver_webhook_deliveryTool(cfg), + tools_code_security.CreateCode_security_get_configurations_for_enterpriseTool(cfg), + tools_code_security.CreateCode_security_create_configuration_for_enterpriseTool(cfg), + tools_repos.CreateRepos_redeliver_webhook_deliveryTool(cfg), + tools_users.CreateUsers_list_attestations_bulkTool(cfg), + tools_emojis.CreateEmojis_getTool(cfg), + tools_actions.CreateActions_force_cancel_workflow_runTool(cfg), + tools_reactions.CreateReactions_list_for_issueTool(cfg), + tools_reactions.CreateReactions_create_for_issueTool(cfg), + tools_classroom.CreateClassroom_list_accepted_assignments_for_an_assignmentTool(cfg), + tools_repos.CreateRepos_get_webhook_config_for_repoTool(cfg), + tools_repos.CreateRepos_update_webhook_config_for_repoTool(cfg), + tools_issues.CreateIssues_list_events_for_repoTool(cfg), + tools_codespaces.CreateCodespaces_list_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_create_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_selected_repositories_enabled_github_actions_organizationTool(cfg), + tools_actions.CreateActions_set_selected_repositories_enabled_github_actions_organizationTool(cfg), + tools_copilot.CreateCopilot_cancel_copilot_seat_assignment_for_teamsTool(cfg), + tools_copilot.CreateCopilot_add_copilot_seats_for_teamsTool(cfg), + tools_classroom.CreateClassroom_get_assignment_gradesTool(cfg), + tools_actions.CreateActions_list_workflow_runs_for_repoTool(cfg), + tools_gists.CreateGists_list_commentsTool(cfg), + tools_gists.CreateGists_create_commentTool(cfg), + tools_copilot.CreateCopilot_cancel_copilot_seat_assignment_for_usersTool(cfg), + tools_copilot.CreateCopilot_add_copilot_seats_for_usersTool(cfg), + tools_repos.CreateRepos_get_all_environmentsTool(cfg), + tools_orgs.CreateOrgs_cancel_invitationTool(cfg), + tools_orgs.CreateOrgs_delete_attestations_by_subject_digestTool(cfg), + tools_repos.CreateRepos_get_org_rulesetsTool(cfg), + tools_repos.CreateRepos_create_org_rulesetTool(cfg), + tools_repos.CreateRepos_list_branchesTool(cfg), + tools_repos.CreateRepos_list_webhook_deliveriesTool(cfg), + tools_actions.CreateActions_get_github_actions_permissions_repositoryTool(cfg), + tools_actions.CreateActions_set_github_actions_permissions_repositoryTool(cfg), + tools_actions.CreateActions_list_org_variablesTool(cfg), + tools_actions.CreateActions_create_org_variableTool(cfg), + tools_activity.CreateActivity_list_watched_repos_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_get_all_package_versions_for_package_owned_by_orgTool(cfg), + tools_orgs.CreateApi_insights_get_user_statsTool(cfg), + tools_orgs.CreateOrgs_get_org_roleTool(cfg), + tools_packages.CreatePackages_list_docker_migration_conflicting_packages_for_userTool(cfg), + tools_apps.CreateApps_get_subscription_plan_for_accountTool(cfg), + tools_repos.CreateRepos_list_deployment_statusesTool(cfg), + tools_repos.CreateRepos_create_deployment_statusTool(cfg), + tools_orgs.CreateApi_insights_get_subject_statsTool(cfg), + tools_copilot.CreateCopilot_copilot_metrics_for_organizationTool(cfg), + tools_repos.CreateRepos_remove_status_check_protectionTool(cfg), + tools_repos.CreateRepos_get_status_checks_protectionTool(cfg), + tools_repos.CreateRepos_update_status_check_protectionTool(cfg), + tools_issues.CreateIssues_list_labels_for_milestoneTool(cfg), + tools_orgs.CreateOrgs_list_failed_invitationsTool(cfg), + tools_licenses.CreateLicenses_getTool(cfg), + tools_repos.CreateRepos_list_release_assetsTool(cfg), + tools_repos.CreateRepos_delete_org_rulesetTool(cfg), + tools_repos.CreateRepos_get_org_rulesetTool(cfg), + tools_repos.CreateRepos_update_org_rulesetTool(cfg), + tools_actions.CreateActions_get_workflow_run_attemptTool(cfg), + tools_actions.CreateActions_create_environment_variableTool(cfg), + tools_actions.CreateActions_list_environment_variablesTool(cfg), + tools_actions.CreateActions_get_hosted_runners_limits_for_orgTool(cfg), + tools_users.CreateUsers_list_ssh_signing_keys_for_userTool(cfg), + tools_checks.CreateChecks_rerequest_suiteTool(cfg), + tools_issues.CreateIssues_delete_commentTool(cfg), + tools_issues.CreateIssues_get_commentTool(cfg), + tools_issues.CreateIssues_update_commentTool(cfg), + tools_codespaces.CreateCodespaces_create_with_pr_for_authenticated_userTool(cfg), + tools_orgs.CreateApi_insights_get_time_stats_by_userTool(cfg), + tools_teams.CreateTeams_add_or_update_membership_for_user_in_orgTool(cfg), + tools_teams.CreateTeams_remove_membership_for_user_in_orgTool(cfg), + tools_teams.CreateTeams_get_membership_for_user_in_orgTool(cfg), + tools_git.CreateGit_get_treeTool(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_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_packages.CreatePackages_restore_package_version_for_authenticated_userTool(cfg), + tools_teams.CreateTeams_list_members_in_orgTool(cfg), + tools_actions.CreateActions_re_run_workflowTool(cfg), + tools_orgs.CreateOrgs_get_all_custom_propertiesTool(cfg), + tools_orgs.CreateOrgs_create_or_update_custom_propertiesTool(cfg), + tools_activity.CreateActivity_list_org_events_for_authenticated_userTool(cfg), + tools_search.CreateSearch_labelsTool(cfg), + tools_repos.CreateRepos_cancel_pages_deploymentTool(cfg), + tools_repos.CreateRepos_get_pages_health_checkTool(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_repos.CreateRepos_set_status_check_contextsTool(cfg), + tools_teams.CreateTeams_list_projects_in_orgTool(cfg), + tools_teams.CreateTeams_listTool(cfg), + tools_teams.CreateTeams_createTool(cfg), + tools_apps.CreateApps_unsuspend_installationTool(cfg), + tools_apps.CreateApps_suspend_installationTool(cfg), + tools_repos.CreateRepos_list_collaboratorsTool(cfg), + tools_orgs.CreateOrgs_list_app_installationsTool(cfg), + tools_repos.CreateRepos_get_deployment_branch_policyTool(cfg), + tools_repos.CreateRepos_update_deployment_branch_policyTool(cfg), + tools_repos.CreateRepos_delete_deployment_branch_policyTool(cfg), + tools_repos.CreateRepos_get_org_rule_suitesTool(cfg), + tools_apps.CreateApps_revoke_installation_access_tokenTool(cfg), + tools_orgs.CreateOrgs_add_security_manager_teamTool(cfg), + tools_orgs.CreateOrgs_remove_security_manager_teamTool(cfg), + tools_codespaces.CreateCodespaces_export_for_authenticated_userTool(cfg), + tools_reactions.CreateReactions_list_for_commit_commentTool(cfg), + tools_reactions.CreateReactions_create_for_commit_commentTool(cfg), + tools_dependabot.CreateDependabot_list_repo_secretsTool(cfg), + tools_apps.CreateApps_list_accounts_for_planTool(cfg), + tools_gists.CreateGists_updateTool(cfg), + tools_gists.CreateGists_deleteTool(cfg), + tools_gists.CreateGists_getTool(cfg), + tools_actions.CreateActions_get_actions_cache_usage_for_orgTool(cfg), + tools_repos.CreateRepos_get_readme_in_directoryTool(cfg), + tools_licenses.CreateLicenses_get_for_repoTool(cfg), + tools_codespaces.CreateCodespaces_check_permissions_for_devcontainerTool(cfg), + tools_codespaces.CreateCodespaces_get_codespaces_for_user_in_orgTool(cfg), + tools_code_security.CreateCode_security_attach_enterprise_configurationTool(cfg), + tools_meta.CreateMeta_rootTool(cfg), + tools_actions.CreateActions_create_registration_token_for_orgTool(cfg), + tools_users.CreateUsers_list_followers_for_authenticated_userTool(cfg), + tools_pulls.CreatePulls_create_reply_for_review_commentTool(cfg), + tools_repos.CreateRepos_download_zipball_archiveTool(cfg), + tools_migrations.CreateMigrations_get_import_statusTool(cfg), + tools_migrations.CreateMigrations_update_importTool(cfg), + tools_migrations.CreateMigrations_start_importTool(cfg), + tools_migrations.CreateMigrations_cancel_importTool(cfg), + tools_codespaces.CreateCodespaces_remove_selected_repo_from_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_add_selected_repo_to_org_secretTool(cfg), + tools_billing.CreateBilling_get_shared_storage_billing_userTool(cfg), + tools_actions.CreateActions_remove_selected_repo_from_org_variableTool(cfg), + tools_actions.CreateActions_add_selected_repo_to_org_variableTool(cfg), + tools_users.CreateUsers_check_blockedTool(cfg), + tools_users.CreateUsers_blockTool(cfg), + tools_users.CreateUsers_unblockTool(cfg), + tools_repos.CreateRepos_list_invitations_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_create_dispatch_eventTool(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_runner_applications_for_orgTool(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_issues.CreateIssues_listTool(cfg), + tools_repos.CreateRepos_get_top_referrersTool(cfg), + tools_activity.CreateActivity_list_notifications_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_mark_notifications_as_readTool(cfg), + tools_orgs.CreateOrgs_deleteTool(cfg), + tools_orgs.CreateOrgs_getTool(cfg), + tools_orgs.CreateOrgs_updateTool(cfg), + tools_pulls.CreatePulls_list_filesTool(cfg), + tools_licenses.CreateLicenses_get_all_commonly_usedTool(cfg), + tools_gists.CreateGists_list_starredTool(cfg), + tools_repos.CreateRepos_list_pull_requests_associated_with_commitTool(cfg), + tools_packages.CreatePackages_delete_package_for_userTool(cfg), + tools_packages.CreatePackages_get_package_for_userTool(cfg), + tools_codespaces.CreateCodespaces_codespace_machines_for_authenticated_userTool(cfg), + tools_git.CreateGit_create_commitTool(cfg), + tools_code_scanning.CreateCode_scanning_list_codeql_databasesTool(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_repos.CreateRepos_get_contributors_statsTool(cfg), + tools_pulls.CreatePulls_list_reviewsTool(cfg), + tools_pulls.CreatePulls_create_reviewTool(cfg), + tools_actions.CreateActions_generate_runner_jitconfig_for_orgTool(cfg), + tools_orgs.CreateOrgs_list_membersTool(cfg), + tools_checks.CreateChecks_list_annotationsTool(cfg), + tools_actions.CreateActions_get_self_hosted_runner_for_repoTool(cfg), + tools_actions.CreateActions_delete_self_hosted_runner_from_repoTool(cfg), + tools_repos.CreateRepos_list_activitiesTool(cfg), + tools_orgs.CreateOrgs_delete_webhookTool(cfg), + tools_orgs.CreateOrgs_get_webhookTool(cfg), + tools_orgs.CreateOrgs_update_webhookTool(cfg), + tools_packages.CreatePackages_list_docker_migration_conflicting_packages_for_authenticated_userTool(cfg), + tools_security_advisories.CreateSecurity_advisories_list_repository_advisoriesTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_repository_advisoryTool(cfg), + tools_repos.CreateRepos_list_comments_for_commitTool(cfg), + tools_repos.CreateRepos_create_commit_commentTool(cfg), + tools_billing.CreateBilling_get_github_billing_usage_report_userTool(cfg), + tools_actions.CreateActions_download_workflow_run_logsTool(cfg), + tools_actions.CreateActions_delete_workflow_run_logsTool(cfg), + tools_secret_scanning.CreateSecret_scanning_create_push_protection_bypassTool(cfg), + tools_gists.CreateGists_forkTool(cfg), + tools_gists.CreateGists_list_forksTool(cfg), + tools_actions.CreateActions_create_workflow_dispatchTool(cfg), + tools_copilot.CreateCopilot_copilot_metrics_for_teamTool(cfg), + tools_codespaces.CreateCodespaces_get_public_key_for_authenticated_userTool(cfg), + tools_actions.CreateActions_get_actions_cache_usageTool(cfg), + tools_actions.CreateActions_list_repo_secretsTool(cfg), + tools_actions.CreateActions_list_jobs_for_workflow_runTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_in_orgTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_in_orgTool(cfg), + tools_dependency_graph.CreateDependency_graph_create_repository_snapshotTool(cfg), + tools_orgs.CreateApi_insights_get_time_stats_by_actorTool(cfg), + tools_billing.CreateBilling_get_shared_storage_billing_orgTool(cfg), + tools_code_security.CreateCode_security_attach_configurationTool(cfg), + tools_actions.CreateActions_set_selected_repos_for_org_variableTool(cfg), + tools_actions.CreateActions_list_selected_repos_for_org_variableTool(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_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_repos.CreateRepos_disable_vulnerability_alertsTool(cfg), + tools_repos.CreateRepos_check_vulnerability_alertsTool(cfg), + tools_repos.CreateRepos_enable_vulnerability_alertsTool(cfg), + tools_repos.CreateRepos_decline_invitation_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_accept_invitation_for_authenticated_userTool(cfg), + tools_teams.CreateTeams_list_pending_invitations_legacyTool(cfg), + tools_orgs.CreateOrgs_list_webhooksTool(cfg), + tools_orgs.CreateOrgs_create_webhookTool(cfg), + tools_actions.CreateActions_delete_actions_cache_by_keyTool(cfg), + tools_actions.CreateActions_get_actions_cache_listTool(cfg), + tools_code_scanning.CreateCode_scanning_get_sarifTool(cfg), + tools_repos.CreateRepos_create_commit_statusTool(cfg), + tools_pulls.CreatePulls_delete_review_commentTool(cfg), + tools_pulls.CreatePulls_get_review_commentTool(cfg), + tools_pulls.CreatePulls_update_review_commentTool(cfg), + tools_users.CreateUsers_get_public_ssh_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_delete_public_ssh_key_for_authenticated_userTool(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_code_scanning.CreateCode_scanning_get_default_setupTool(cfg), + tools_code_scanning.CreateCode_scanning_update_default_setupTool(cfg), + tools_issues.CreateIssues_remove_sub_issueTool(cfg), + tools_repos.CreateRepos_rename_branchTool(cfg), + tools_search.CreateSearch_usersTool(cfg), + tools_reactions.CreateReactions_delete_for_team_discussion_commentTool(cfg), + tools_migrations.CreateMigrations_start_for_authenticated_userTool(cfg), + tools_migrations.CreateMigrations_list_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_get_webhook_deliveryTool(cfg), + tools_actions.CreateActions_list_repo_variablesTool(cfg), + tools_actions.CreateActions_create_repo_variableTool(cfg), + tools_activity.CreateActivity_list_repos_starred_by_userTool(cfg), + tools_git.CreateGit_get_refTool(cfg), + tools_code_security.CreateCode_security_detach_configurationTool(cfg), + tools_orgs.CreateOrgs_list_memberships_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_create_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_deploymentsTool(cfg), + tools_repos.CreateRepos_create_deploymentTool(cfg), + tools_actions.CreateActions_disable_workflowTool(cfg), + tools_codespaces.CreateCodespaces_delete_codespaces_access_usersTool(cfg), + tools_codespaces.CreateCodespaces_set_codespaces_access_usersTool(cfg), + tools_actions.CreateActions_remove_custom_label_from_self_hosted_runner_for_orgTool(cfg), + tools_migrations.CreateMigrations_set_lfs_preferenceTool(cfg), + tools_repos.CreateRepos_get_pages_buildTool(cfg), + tools_repos.CreateRepos_get_release_by_tagTool(cfg), + tools_users.CreateUsers_delete_ssh_signing_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_get_ssh_signing_key_for_authenticated_userTool(cfg), + tools_apps.CreateApps_list_installations_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_unstar_repo_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_check_repo_is_starred_by_authenticated_userTool(cfg), + tools_activity.CreateActivity_star_repo_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_listTool(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_review_pat_grant_requestTool(cfg), + tools_teams.CreateTeams_list_for_authenticated_userTool(cfg), + tools_apps.CreateApps_get_authenticatedTool(cfg), + tools_actions.CreateActions_get_actions_cache_usage_by_repo_for_orgTool(cfg), + tools_orgs.CreateApi_insights_get_summary_stats_by_actorTool(cfg), + tools_dependabot.CreateDependabot_list_selected_repos_for_org_secretTool(cfg), + tools_dependabot.CreateDependabot_set_selected_repos_for_org_secretTool(cfg), + tools_dependabot.CreateDependabot_get_repo_public_keyTool(cfg), + tools_migrations.CreateMigrations_map_commit_authorTool(cfg), + tools_repos.CreateRepos_get_latest_pages_buildTool(cfg), + tools_secret_scanning.CreateSecret_scanning_get_scan_historyTool(cfg), + tools_repos.CreateRepos_get_repo_rule_suiteTool(cfg), + tools_activity.CreateActivity_list_repos_watched_by_userTool(cfg), + tools_actions.CreateActions_get_repo_variableTool(cfg), + tools_actions.CreateActions_update_repo_variableTool(cfg), + tools_actions.CreateActions_delete_repo_variableTool(cfg), + tools_orgs.CreateApi_insights_get_summary_stats_by_userTool(cfg), + tools_orgs.CreateOrgs_get_membership_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_update_membership_for_authenticated_userTool(cfg), + tools_apps.CreateApps_get_by_slugTool(cfg), + tools_orgs.CreateOrgs_list_security_manager_teamsTool(cfg), + tools_code_scanning.CreateCode_scanning_list_recent_analysesTool(cfg), + tools_copilot.CreateCopilot_get_copilot_seat_details_for_userTool(cfg), + tools_apps.CreateApps_list_accounts_for_plan_stubbedTool(cfg), + tools_migrations.CreateMigrations_unlock_repo_for_authenticated_userTool(cfg), + tools_apps.CreateApps_list_subscriptions_for_authenticated_user_stubbedTool(cfg), + tools_search.CreateSearch_reposTool(cfg), + tools_apps.CreateApps_get_webhook_deliveryTool(cfg), + tools_orgs.CreateApi_insights_get_time_statsTool(cfg), + tools_actions.CreateActions_list_workflow_run_artifactsTool(cfg), + tools_checks.CreateChecks_rerequest_runTool(cfg), + tools_repos.CreateRepos_delete_deploymentTool(cfg), + tools_repos.CreateRepos_get_deploymentTool(cfg), + tools_interactions.CreateInteractions_set_restrictions_for_authenticated_userTool(cfg), + tools_interactions.CreateInteractions_remove_restrictions_for_authenticated_userTool(cfg), + tools_interactions.CreateInteractions_get_restrictions_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_delete_autolinkTool(cfg), + tools_repos.CreateRepos_get_autolinkTool(cfg), + tools_actions.CreateActions_list_self_hosted_runners_for_orgTool(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_activity.CreateActivity_list_public_eventsTool(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_codes_of_conduct.CreateCodes_of_conduct_get_all_codes_of_conductTool(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_packages.CreatePackages_list_packages_for_authenticated_userTool(cfg), + tools_code_security.CreateCode_security_set_configuration_as_default_for_enterpriseTool(cfg), + tools_repos.CreateRepos_get_punch_card_statsTool(cfg), + tools_search.CreateSearch_issues_and_pull_requestsTool(cfg), + tools_packages.CreatePackages_list_docker_migration_conflicting_packages_for_organizationTool(cfg), + tools_activity.CreateActivity_delete_repo_subscriptionTool(cfg), + tools_activity.CreateActivity_get_repo_subscriptionTool(cfg), + tools_activity.CreateActivity_set_repo_subscriptionTool(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_repos.CreateRepos_update_releaseTool(cfg), + tools_repos.CreateRepos_delete_releaseTool(cfg), + tools_repos.CreateRepos_get_releaseTool(cfg), + tools_codespaces.CreateCodespaces_remove_repository_for_secret_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_add_repository_for_secret_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_list_invitation_teamsTool(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_repos.CreateRepos_get_commit_signature_protectionTool(cfg), + tools_repos.CreateRepos_create_commit_signature_protectionTool(cfg), + tools_repos.CreateRepos_delete_commit_signature_protectionTool(cfg), + tools_repos.CreateRepos_create_pages_deploymentTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_alerts_for_repoTool(cfg), + tools_activity.CreateActivity_list_repos_starred_by_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_delete_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_get_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_update_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_delete_access_restrictionsTool(cfg), + tools_repos.CreateRepos_get_access_restrictionsTool(cfg), + tools_projects.CreateProjects_create_columnTool(cfg), + tools_projects.CreateProjects_list_columnsTool(cfg), + tools_pulls.CreatePulls_dismiss_reviewTool(cfg), + tools_teams.CreateTeams_delete_legacyTool(cfg), + tools_teams.CreateTeams_get_legacyTool(cfg), + tools_teams.CreateTeams_update_legacyTool(cfg), + tools_apps.CreateApps_list_webhook_deliveriesTool(cfg), + tools_apps.CreateApps_get_user_installationTool(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_apps.CreateApps_delete_tokenTool(cfg), + tools_apps.CreateApps_reset_tokenTool(cfg), + tools_apps.CreateApps_check_tokenTool(cfg), + tools_users.CreateUsers_delete_gpg_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_get_gpg_key_for_authenticated_userTool(cfg), + tools_code_scanning.CreateCode_scanning_delete_codeql_databaseTool(cfg), + tools_code_scanning.CreateCode_scanning_get_codeql_databaseTool(cfg), + tools_repos.CreateRepos_compare_commitsTool(cfg), + tools_teams.CreateTeams_remove_repo_in_orgTool(cfg), + tools_teams.CreateTeams_check_permissions_for_repo_in_orgTool(cfg), + tools_teams.CreateTeams_add_or_update_repo_permissions_in_orgTool(cfg), + tools_repos.CreateRepos_get_custom_properties_valuesTool(cfg), + tools_repos.CreateRepos_create_or_update_custom_properties_valuesTool(cfg), + tools_code_scanning.CreateCode_scanning_get_variant_analysisTool(cfg), + tools_repos.CreateRepos_list_commit_comments_for_repoTool(cfg), + tools_meta.CreateMeta_getTool(cfg), + tools_repos.CreateRepos_remove_collaboratorTool(cfg), + tools_repos.CreateRepos_check_collaboratorTool(cfg), + tools_repos.CreateRepos_add_collaboratorTool(cfg), + tools_dependabot.CreateDependabot_get_org_public_keyTool(cfg), + tools_git.CreateGit_update_refTool(cfg), + tools_git.CreateGit_delete_refTool(cfg), + tools_pulls.CreatePulls_delete_pending_reviewTool(cfg), + tools_pulls.CreatePulls_get_reviewTool(cfg), + tools_pulls.CreatePulls_update_reviewTool(cfg), + tools_repos.CreateRepos_get_commitTool(cfg), + tools_apps.CreateApps_get_repo_installationTool(cfg), + tools_repos.CreateRepos_list_branches_for_head_commitTool(cfg), + tools_code_security.CreateCode_security_get_repositories_for_configurationTool(cfg), + tools_reactions.CreateReactions_list_for_pull_request_review_commentTool(cfg), + tools_reactions.CreateReactions_create_for_pull_request_review_commentTool(cfg), + tools_users.CreateUsers_delete_attestations_bulkTool(cfg), + tools_checks.CreateChecks_list_for_suiteTool(cfg), + tools_code_security.CreateCode_security_get_configurations_for_orgTool(cfg), + tools_code_security.CreateCode_security_create_configurationTool(cfg), + tools_repos.CreateRepos_get_org_rule_suiteTool(cfg), + tools_actions.CreateActions_re_run_job_for_workflow_runTool(cfg), + tools_activity.CreateActivity_list_public_org_eventsTool(cfg), + tools_dependabot.CreateDependabot_list_alerts_for_enterpriseTool(cfg), + tools_teams.CreateTeams_list_repos_legacyTool(cfg), + tools_repos.CreateRepos_list_invitationsTool(cfg), + tools_repos.CreateRepos_list_attestationsTool(cfg), + tools_actions.CreateActions_review_custom_gates_for_runTool(cfg), + tools_actions.CreateActions_remove_repo_access_to_self_hosted_runner_group_in_orgTool(cfg), + tools_actions.CreateActions_add_repo_access_to_self_hosted_runner_group_in_orgTool(cfg), + tools_repos.CreateRepos_delete_fileTool(cfg), + tools_repos.CreateRepos_get_contentTool(cfg), + tools_repos.CreateRepos_create_or_update_file_contentsTool(cfg), + tools_issues.CreateIssues_list_for_orgTool(cfg), + tools_repos.CreateRepos_get_viewsTool(cfg), + tools_classroom.CreateClassroom_list_assignments_for_a_classroomTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_alerts_for_enterpriseTool(cfg), + tools_actions.CreateActions_create_remove_token_for_repoTool(cfg), + tools_apps.CreateApps_list_repos_accessible_to_installationTool(cfg), + tools_codespaces.CreateCodespaces_get_org_public_keyTool(cfg), + tools_orgs.CreateOrgs_list_attestationsTool(cfg), + tools_checks.CreateChecks_getTool(cfg), + tools_checks.CreateChecks_updateTool(cfg), + tools_apps.CreateApps_list_subscriptions_for_authenticated_userTool(cfg), + tools_checks.CreateChecks_list_for_refTool(cfg), + tools_codespaces.CreateCodespaces_list_repositories_for_secret_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_set_repositories_for_secret_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_commitsTool(cfg), + tools_activity.CreateActivity_list_public_events_for_repo_networkTool(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_repos.CreateRepos_get_collaborator_permission_levelTool(cfg), + tools_actions.CreateActions_get_repo_public_keyTool(cfg), + tools_actions.CreateActions_get_allowed_actions_organizationTool(cfg), + tools_actions.CreateActions_set_allowed_actions_organizationTool(cfg), + tools_git.CreateGit_get_commitTool(cfg), + tools_actions.CreateActions_get_workflow_run_usageTool(cfg), + tools_apps.CreateApps_get_org_installationTool(cfg), + tools_packages.CreatePackages_list_packages_for_organizationTool(cfg), + tools_billing.CreateBilling_get_github_actions_billing_orgTool(cfg), + tools_apps.CreateApps_get_webhook_config_for_appTool(cfg), + tools_apps.CreateApps_update_webhook_config_for_appTool(cfg), + tools_codespaces.CreateCodespaces_start_for_authenticated_userTool(cfg), + tools_actions.CreateActions_delete_self_hosted_runner_group_from_orgTool(cfg), + tools_actions.CreateActions_get_self_hosted_runner_group_for_orgTool(cfg), + tools_actions.CreateActions_update_self_hosted_runner_group_for_orgTool(cfg), + tools_issues.CreateIssues_list_for_repoTool(cfg), + tools_issues.CreateIssues_createTool(cfg), + tools_code_scanning.CreateCode_scanning_list_alerts_for_repoTool(cfg), + tools_codespaces.CreateCodespaces_list_secrets_for_authenticated_userTool(cfg), + tools_apps.CreateApps_delete_authorizationTool(cfg), + tools_credentials.CreateCredentials_revokeTool(cfg), + tools_orgs.CreateOrgs_update_issue_typeTool(cfg), + tools_orgs.CreateOrgs_delete_issue_typeTool(cfg), + tools_issues.CreateIssues_list_assigneesTool(cfg), + tools_repos.CreateRepos_list_forksTool(cfg), + tools_repos.CreateRepos_create_forkTool(cfg), + tools_migrations.CreateMigrations_list_repos_for_orgTool(cfg), + tools_teams.CreateTeams_update_discussion_in_orgTool(cfg), + tools_teams.CreateTeams_delete_discussion_in_orgTool(cfg), + tools_teams.CreateTeams_get_discussion_in_orgTool(cfg), + tools_checks.CreateChecks_list_suites_for_refTool(cfg), + tools_packages.CreatePackages_delete_package_version_for_userTool(cfg), + tools_packages.CreatePackages_get_package_version_for_userTool(cfg), + tools_orgs.CreateOrgs_enable_or_disable_security_product_on_all_org_reposTool(cfg), + tools_repos.CreateRepos_list_for_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_actions.CreateActions_get_environment_public_keyTool(cfg), + tools_repos.CreateRepos_delete_branch_protectionTool(cfg), + tools_repos.CreateRepos_get_branch_protectionTool(cfg), + tools_repos.CreateRepos_update_branch_protectionTool(cfg), + tools_actions.CreateActions_list_environment_secretsTool(cfg), + tools_teams.CreateTeams_list_members_legacyTool(cfg), + tools_search.CreateSearch_commitsTool(cfg), + tools_codespaces.CreateCodespaces_list_org_secretsTool(cfg), + tools_repos.CreateRepos_list_releasesTool(cfg), + tools_repos.CreateRepos_create_releaseTool(cfg), + tools_git.CreateGit_get_blobTool(cfg), + tools_copilot.CreateCopilot_list_copilot_seatsTool(cfg), + tools_codespaces.CreateCodespaces_repo_machines_for_authenticated_userTool(cfg), + tools_orgs.CreateOrgs_remove_outside_collaboratorTool(cfg), + tools_orgs.CreateOrgs_convert_member_to_outside_collaboratorTool(cfg), + tools_actions.CreateActions_list_self_hosted_runner_groups_for_orgTool(cfg), + tools_actions.CreateActions_create_self_hosted_runner_group_for_orgTool(cfg), + tools_git.CreateGit_get_tagTool(cfg), + tools_orgs.CreateOrgs_list_pat_grant_repositoriesTool(cfg), + tools_actions.CreateActions_list_runner_applications_for_repoTool(cfg), + tools_repos.CreateRepos_list_tag_protectionTool(cfg), + tools_repos.CreateRepos_create_tag_protectionTool(cfg), + tools_actions.CreateActions_get_reviews_for_runTool(cfg), + tools_orgs.CreateOrgs_list_outside_collaboratorsTool(cfg), + tools_repos.CreateRepos_get_participation_statsTool(cfg), + tools_pulls.CreatePulls_remove_requested_reviewersTool(cfg), + tools_pulls.CreatePulls_list_requested_reviewersTool(cfg), + tools_pulls.CreatePulls_request_reviewersTool(cfg), + tools_packages.CreatePackages_get_all_package_versions_for_package_owned_by_userTool(cfg), + tools_users.CreateUsers_list_blocked_by_authenticated_userTool(cfg), + tools_projects.CreateProjects_remove_collaboratorTool(cfg), + tools_projects.CreateProjects_add_collaboratorTool(cfg), + tools_issues.CreateIssues_check_user_can_be_assignedTool(cfg), + tools_activity.CreateActivity_list_events_for_authenticated_userTool(cfg), + tools_teams.CreateTeams_list_repos_in_orgTool(cfg), + tools_meta.CreateMeta_get_zenTool(cfg), + tools_repos.CreateRepos_get_deployment_statusTool(cfg), + tools_repos.CreateRepos_get_branchTool(cfg), + tools_activity.CreateActivity_list_received_public_events_for_userTool(cfg), + tools_actions.CreateActions_set_custom_oidc_sub_claim_for_repoTool(cfg), + tools_actions.CreateActions_get_custom_oidc_sub_claim_for_repoTool(cfg), + tools_git.CreateGit_create_treeTool(cfg), + tools_repos.CreateRepos_list_pages_buildsTool(cfg), + tools_repos.CreateRepos_request_pages_buildTool(cfg), + tools_actions.CreateActions_get_hosted_runners_github_owned_images_for_orgTool(cfg), + tools_actions.CreateActions_set_allowed_actions_repositoryTool(cfg), + tools_actions.CreateActions_get_allowed_actions_repositoryTool(cfg), + tools_repos.CreateRepos_delete_webhookTool(cfg), + tools_repos.CreateRepos_get_webhookTool(cfg), + tools_repos.CreateRepos_update_webhookTool(cfg), + tools_users.CreateUsers_get_authenticatedTool(cfg), + tools_users.CreateUsers_update_authenticatedTool(cfg), + tools_reactions.CreateReactions_list_for_issue_commentTool(cfg), + tools_reactions.CreateReactions_create_for_issue_commentTool(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_repos.CreateRepos_generate_release_notesTool(cfg), + tools_actions.CreateActions_create_registration_token_for_repoTool(cfg), + tools_teams.CreateTeams_list_discussions_in_orgTool(cfg), + tools_teams.CreateTeams_create_discussion_in_orgTool(cfg), + tools_repos.CreateRepos_ping_webhookTool(cfg), + tools_repos.CreateRepos_delete_invitationTool(cfg), + tools_repos.CreateRepos_update_invitationTool(cfg), + tools_migrations.CreateMigrations_get_commit_authorsTool(cfg), + tools_apps.CreateApps_list_plans_stubbedTool(cfg), + tools_repos.CreateRepos_download_tarball_archiveTool(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_codespaces.CreateCodespaces_pre_flight_with_repo_for_authenticated_userTool(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_issues.CreateIssues_remove_assigneesTool(cfg), + tools_issues.CreateIssues_add_assigneesTool(cfg), + tools_code_scanning.CreateCode_scanning_commit_autofixTool(cfg), + tools_repos.CreateRepos_remove_user_access_restrictionsTool(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_codespaces.CreateCodespaces_delete_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_get_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_create_or_update_org_secretTool(cfg), + tools_migrations.CreateMigrations_list_repos_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_selected_repos_for_org_secretTool(cfg), + tools_actions.CreateActions_set_selected_repos_for_org_secretTool(cfg), + tools_repos.CreateRepos_get_latest_releaseTool(cfg), + tools_repos.CreateRepos_get_repo_rule_suitesTool(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_actions.CreateActions_get_workflow_access_to_repositoryTool(cfg), + tools_actions.CreateActions_set_workflow_access_to_repositoryTool(cfg), + tools_actions.CreateActions_get_hosted_runners_platforms_for_orgTool(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_classroom.CreateClassroom_get_an_assignmentTool(cfg), + tools_packages.CreatePackages_delete_package_version_for_orgTool(cfg), + tools_packages.CreatePackages_get_package_version_for_organizationTool(cfg), + tools_users.CreateUsers_list_social_accounts_for_userTool(cfg), + tools_orgs.CreateOrgs_list_for_authenticated_userTool(cfg), + tools_codes_of_conduct.CreateCodes_of_conduct_get_conduct_codeTool(cfg), + tools_packages.CreatePackages_restore_package_for_orgTool(cfg), + tools_orgs.CreateOrgs_list_pat_grantsTool(cfg), + tools_orgs.CreateOrgs_update_pat_accessesTool(cfg), + tools_projects.CreateProjects_delete_cardTool(cfg), + tools_projects.CreateProjects_get_cardTool(cfg), + tools_projects.CreateProjects_update_cardTool(cfg), + tools_users.CreateUsers_listTool(cfg), + tools_actions.CreateActions_get_org_variableTool(cfg), + tools_actions.CreateActions_update_org_variableTool(cfg), + tools_actions.CreateActions_delete_org_variableTool(cfg), + tools_codespaces.CreateCodespaces_delete_from_organizationTool(cfg), + tools_actions.CreateActions_list_org_secretsTool(cfg), + tools_codespaces.CreateCodespaces_get_export_details_for_authenticated_userTool(cfg), + tools_users.CreateUsers_list_public_keys_for_userTool(cfg), + tools_migrations.CreateMigrations_delete_archive_for_authenticated_userTool(cfg), + tools_migrations.CreateMigrations_get_archive_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_get_commit_activity_statsTool(cfg), + tools_orgs.CreateOrgs_list_public_membersTool(cfg), + tools_reactions.CreateReactions_delete_for_team_discussionTool(cfg), + tools_actions.CreateActions_list_github_hosted_runners_in_group_for_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_reactions.CreateReactions_delete_for_issueTool(cfg), + tools_actions.CreateActions_create_remove_token_for_orgTool(cfg), + tools_repos.CreateRepos_get_repo_ruleset_versionTool(cfg), + tools_pulls.CreatePulls_updateTool(cfg), + tools_pulls.CreatePulls_getTool(cfg), + tools_gists.CreateGists_list_publicTool(cfg), + tools_git.CreateGit_create_refTool(cfg), + tools_issues.CreateIssues_list_labels_on_issueTool(cfg), + tools_issues.CreateIssues_add_labelsTool(cfg), + tools_issues.CreateIssues_set_labelsTool(cfg), + tools_issues.CreateIssues_remove_all_labelsTool(cfg), + tools_repos.CreateRepos_get_branch_rulesTool(cfg), + tools_migrations.CreateMigrations_delete_archive_for_orgTool(cfg), + tools_migrations.CreateMigrations_download_archive_for_orgTool(cfg), + tools_actions.CreateActions_delete_environment_variableTool(cfg), + tools_actions.CreateActions_get_environment_variableTool(cfg), + tools_actions.CreateActions_update_environment_variableTool(cfg), + tools_activity.CreateActivity_get_feedsTool(cfg), + tools_hosted_compute.CreateHosted_compute_list_network_configurations_for_orgTool(cfg), + tools_hosted_compute.CreateHosted_compute_create_network_configuration_for_orgTool(cfg), + tools_apps.CreateApps_delete_installationTool(cfg), + tools_apps.CreateApps_get_installationTool(cfg), + tools_repos.CreateRepos_create_webhookTool(cfg), + tools_repos.CreateRepos_list_webhooksTool(cfg), + tools_issues.CreateIssues_list_milestonesTool(cfg), + tools_issues.CreateIssues_create_milestoneTool(cfg), + tools_teams.CreateTeams_list_child_in_orgTool(cfg), + tools_actions.CreateActions_approve_workflow_runTool(cfg), + tools_users.CreateUsers_get_by_usernameTool(cfg), + tools_projects.CreateProjects_list_for_repoTool(cfg), + tools_projects.CreateProjects_create_for_repoTool(cfg), + tools_repos.CreateRepos_get_all_topicsTool(cfg), + tools_repos.CreateRepos_replace_all_topicsTool(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_users.CreateUsers_get_context_for_userTool(cfg), + tools_repos.CreateRepos_list_publicTool(cfg), + tools_pulls.CreatePulls_list_review_commentsTool(cfg), + tools_pulls.CreatePulls_create_review_commentTool(cfg), + tools_orgs.CreateOrgs_ping_webhookTool(cfg), + tools_repos.CreateRepos_get_custom_deployment_protection_ruleTool(cfg), + tools_repos.CreateRepos_disable_deployment_protection_ruleTool(cfg), + tools_orgs.CreateOrgs_list_org_role_usersTool(cfg), + tools_packages.CreatePackages_restore_package_for_authenticated_userTool(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_search.CreateSearch_codeTool(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_re_run_workflow_failed_jobsTool(cfg), + tools_projects.CreateProjects_delete_columnTool(cfg), + tools_projects.CreateProjects_get_columnTool(cfg), + tools_projects.CreateProjects_update_columnTool(cfg), + tools_orgs.CreateOrgs_get_org_ruleset_historyTool(cfg), + tools_migrations.CreateMigrations_get_status_for_orgTool(cfg), + tools_dependency_graph.CreateDependency_graph_diff_rangeTool(cfg), + tools_users.CreateUsers_set_primary_email_visibility_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_get_all_package_versions_for_package_owned_by_authenticated_userTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_legacyTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_legacyTool(cfg), + tools_codespaces.CreateCodespaces_stop_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_create_using_templateTool(cfg), + tools_projects.CreateProjects_move_cardTool(cfg), + tools_issues.CreateIssues_check_user_can_be_assigned_to_issueTool(cfg), + tools_code_security.CreateCode_security_get_configuration_for_repositoryTool(cfg), + tools_actions.CreateActions_remove_custom_label_from_self_hosted_runner_for_repoTool(cfg), + tools_classroom.CreateClassroom_get_a_classroomTool(cfg), + tools_dependabot.CreateDependabot_repository_access_for_orgTool(cfg), + tools_dependabot.CreateDependabot_update_repository_access_for_orgTool(cfg), + tools_issues.CreateIssues_list_comments_for_repoTool(cfg), + tools_billing.CreateBilling_get_github_billing_usage_report_orgTool(cfg), + tools_projects.CreateProjects_create_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_list_repo_notifications_for_authenticated_userTool(cfg), + tools_activity.CreateActivity_mark_repo_notifications_as_readTool(cfg), + tools_code_security.CreateCode_security_get_repositories_for_enterprise_configurationTool(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_gitignore.CreateGitignore_get_all_templatesTool(cfg), + tools_actions.CreateActions_list_jobs_for_workflow_run_attemptTool(cfg), + tools_orgs.CreateOrgs_list_pending_invitationsTool(cfg), + tools_orgs.CreateOrgs_create_invitationTool(cfg), + tools_orgs.CreateOrgs_review_pat_grant_requests_in_bulkTool(cfg), + tools_orgs.CreateOrgs_list_pat_grant_requestsTool(cfg), + tools_actions.CreateActions_enable_workflowTool(cfg), + tools_pulls.CreatePulls_list_commitsTool(cfg), + tools_users.CreateUsers_list_gpg_keys_for_userTool(cfg), + tools_repos.CreateRepos_get_repo_rulesetsTool(cfg), + tools_repos.CreateRepos_create_repo_rulesetTool(cfg), + tools_actions.CreateActions_delete_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_get_hosted_runner_for_orgTool(cfg), + tools_actions.CreateActions_update_hosted_runner_for_orgTool(cfg), + tools_apps.CreateApps_get_subscription_plan_for_account_stubbedTool(cfg), + tools_repos.CreateRepos_disable_private_vulnerability_reportingTool(cfg), + tools_repos.CreateRepos_check_private_vulnerability_reportingTool(cfg), + tools_repos.CreateRepos_enable_private_vulnerability_reportingTool(cfg), + tools_reactions.CreateReactions_delete_for_releaseTool(cfg), + tools_migrations.CreateMigrations_unlock_repo_for_orgTool(cfg), + tools_projects.CreateProjects_list_for_userTool(cfg), + tools_orgs.CreateOrgs_list_org_rolesTool(cfg), + tools_projects.CreateProjects_list_collaboratorsTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_locations_for_alertTool(cfg), + tools_git.CreateGit_list_matching_refsTool(cfg), + tools_actions.CreateActions_download_artifactTool(cfg), + tools_migrations.CreateMigrations_list_for_orgTool(cfg), + tools_migrations.CreateMigrations_start_for_orgTool(cfg), + tools_pulls.CreatePulls_list_comments_for_reviewTool(cfg), + tools_orgs.CreateOrgs_list_org_role_teamsTool(cfg), + tools_codespaces.CreateCodespaces_stop_in_organizationTool(cfg), + tools_issues.CreateIssues_reprioritize_sub_issueTool(cfg), + tools_users.CreateUsers_delete_attestations_by_idTool(cfg), + tools_gists.CreateGists_get_revisionTool(cfg), + tools_actions.CreateActions_list_self_hosted_runners_for_repoTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_comment_legacyTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_comment_legacyTool(cfg), + tools_projects.CreateProjects_move_columnTool(cfg), + tools_reactions.CreateReactions_delete_for_pull_request_commentTool(cfg), + tools_packages.CreatePackages_delete_package_for_orgTool(cfg), + tools_packages.CreatePackages_get_package_for_organizationTool(cfg), + tools_apps.CreateApps_create_installation_access_tokenTool(cfg), + tools_packages.CreatePackages_list_packages_for_userTool(cfg), + tools_actions.CreateActions_get_github_actions_default_workflow_permissions_organizationTool(cfg), + tools_actions.CreateActions_set_github_actions_default_workflow_permissions_organizationTool(cfg), + tools_repos.CreateRepos_delete_tag_protectionTool(cfg), + tools_pulls.CreatePulls_listTool(cfg), + tools_pulls.CreatePulls_createTool(cfg), + tools_orgs.CreateOrgs_get_org_ruleset_versionTool(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_users.CreateUsers_list_followed_by_authenticated_userTool(cfg), + tools_reactions.CreateReactions_delete_for_commit_commentTool(cfg), + tools_repos.CreateRepos_get_readmeTool(cfg), + tools_users.CreateUsers_list_ssh_signing_keys_for_authenticated_userTool(cfg), + tools_users.CreateUsers_create_ssh_signing_key_for_authenticated_userTool(cfg), + tools_orgs.CreateApi_insights_get_summary_statsTool(cfg), + tools_orgs.CreateOrgs_revoke_all_org_roles_userTool(cfg), + tools_activity.CreateActivity_list_public_events_for_userTool(cfg), + tools_pulls.CreatePulls_update_branchTool(cfg), + tools_repos.CreateRepos_mergeTool(cfg), + tools_codespaces.CreateCodespaces_set_codespaces_accessTool(cfg), + tools_gists.CreateGists_unstarTool(cfg), + tools_gists.CreateGists_check_is_starredTool(cfg), + tools_gists.CreateGists_starTool(cfg), + tools_repos.CreateRepos_list_languagesTool(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_migrations.CreateMigrations_get_status_for_authenticated_userTool(cfg), + tools_actions.CreateActions_get_github_actions_permissions_organizationTool(cfg), + tools_actions.CreateActions_set_github_actions_permissions_organizationTool(cfg), + tools_code_scanning.CreateCode_scanning_delete_analysisTool(cfg), + tools_code_scanning.CreateCode_scanning_get_analysisTool(cfg), + tools_repos.CreateRepos_updateTool(cfg), + tools_repos.CreateRepos_deleteTool(cfg), + tools_repos.CreateRepos_getTool(cfg), + tools_issues.CreateIssues_list_commentsTool(cfg), + tools_issues.CreateIssues_create_commentTool(cfg), + tools_users.CreateUsers_check_person_is_followed_by_authenticatedTool(cfg), + tools_users.CreateUsers_followTool(cfg), + tools_users.CreateUsers_unfollowTool(cfg), + tools_gists.CreateGists_update_commentTool(cfg), + tools_gists.CreateGists_delete_commentTool(cfg), + tools_gists.CreateGists_get_commentTool(cfg), + tools_issues.CreateIssues_getTool(cfg), + tools_issues.CreateIssues_updateTool(cfg), + tools_actions.CreateActions_generate_runner_jitconfig_for_repoTool(cfg), + tools_actions.CreateActions_get_github_actions_default_workflow_permissions_repositoryTool(cfg), + tools_actions.CreateActions_set_github_actions_default_workflow_permissions_repositoryTool(cfg), + tools_issues.CreateIssues_unlockTool(cfg), + tools_issues.CreateIssues_lockTool(cfg), + tools_orgs.CreateOrgs_list_issue_typesTool(cfg), + tools_orgs.CreateOrgs_create_issue_typeTool(cfg), + tools_rate_limit.CreateRate_limit_getTool(cfg), + tools_dependabot.CreateDependabot_list_alerts_for_orgTool(cfg), + tools_actions.CreateActions_download_workflow_run_attempt_logsTool(cfg), + tools_orgs.CreateOrgs_update_pat_accessTool(cfg), + tools_search.CreateSearch_topicsTool(cfg), + tools_secret_scanning.CreateSecret_scanning_get_alertTool(cfg), + tools_secret_scanning.CreateSecret_scanning_update_alertTool(cfg), + tools_repos.CreateRepos_get_clonesTool(cfg), + tools_users.CreateUsers_list_attestationsTool(cfg), + tools_actions.CreateActions_get_job_for_workflow_runTool(cfg), + tools_campaigns.CreateCampaigns_delete_campaignTool(cfg), + tools_campaigns.CreateCampaigns_get_campaign_summaryTool(cfg), + tools_campaigns.CreateCampaigns_update_campaignTool(cfg), + tools_codespaces.CreateCodespaces_list_in_repository_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_create_with_repo_for_authenticated_userTool(cfg), + tools_codespaces.CreateCodespaces_get_repo_public_keyTool(cfg), + tools_repos.CreateRepos_get_code_frequency_statsTool(cfg), + tools_orgs.CreateApi_insights_get_route_stats_by_actorTool(cfg), + tools_actions.CreateActions_list_hosted_runners_for_orgTool(cfg), + tools_actions.CreateActions_create_hosted_runner_for_orgTool(cfg), + tools_apps.CreateApps_list_installation_repos_for_authenticated_userTool(cfg), + tools_apps.CreateApps_list_plansTool(cfg), + tools_codespaces.CreateCodespaces_list_selected_repos_for_org_secretTool(cfg), + tools_codespaces.CreateCodespaces_set_selected_repos_for_org_secretTool(cfg), + tools_orgs.CreateOrgs_list_pat_grant_request_repositoriesTool(cfg), + tools_issues.CreateIssues_remove_labelTool(cfg), + tools_security_advisories.CreateSecurity_advisories_get_global_advisoryTool(cfg), + tools_orgs.CreateOrgs_revoke_all_org_roles_teamTool(cfg), + tools_hosted_compute.CreateHosted_compute_get_network_settings_for_orgTool(cfg), + tools_activity.CreateActivity_list_received_events_for_userTool(cfg), + tools_repos.CreateRepos_merge_upstreamTool(cfg), + tools_teams.CreateTeams_list_discussion_comments_in_orgTool(cfg), + tools_teams.CreateTeams_create_discussion_comment_in_orgTool(cfg), + tools_copilot.CreateCopilot_get_copilot_organization_detailsTool(cfg), + tools_teams.CreateTeams_list_discussion_comments_legacyTool(cfg), + tools_teams.CreateTeams_create_discussion_comment_legacyTool(cfg), + tools_activity.CreateActivity_list_watchers_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_packages.CreatePackages_restore_package_for_userTool(cfg), + tools_teams.CreateTeams_list_discussions_legacyTool(cfg), + tools_teams.CreateTeams_create_discussion_legacyTool(cfg), + tools_packages.CreatePackages_delete_package_version_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_get_package_version_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_list_autolinksTool(cfg), + tools_repos.CreateRepos_create_autolinkTool(cfg), + tools_actions.CreateActions_download_job_logs_for_workflow_runTool(cfg), + tools_meta.CreateMeta_get_all_versionsTool(cfg), + tools_reactions.CreateReactions_list_for_team_discussion_comment_in_orgTool(cfg), + tools_reactions.CreateReactions_create_for_team_discussion_comment_in_orgTool(cfg), + tools_repos.CreateRepos_get_combined_status_for_refTool(cfg), + tools_campaigns.CreateCampaigns_list_org_campaignsTool(cfg), + tools_campaigns.CreateCampaigns_create_campaignTool(cfg), + tools_projects.CreateProjects_list_for_orgTool(cfg), + tools_projects.CreateProjects_create_for_orgTool(cfg), + tools_repos.CreateRepos_get_pages_deploymentTool(cfg), + tools_dependabot.CreateDependabot_list_alerts_for_repoTool(cfg), + tools_repos.CreateRepos_list_commit_statuses_for_refTool(cfg), + tools_private_registries.CreatePrivate_registries_update_org_private_registryTool(cfg), + tools_private_registries.CreatePrivate_registries_delete_org_private_registryTool(cfg), + tools_private_registries.CreatePrivate_registries_get_org_private_registryTool(cfg), + tools_projects.CreateProjects_deleteTool(cfg), + tools_projects.CreateProjects_getTool(cfg), + tools_projects.CreateProjects_updateTool(cfg), + tools_actions.CreateActions_get_workflow_usageTool(cfg), + tools_checks.CreateChecks_get_suiteTool(cfg), + tools_packages.CreatePackages_restore_package_version_for_userTool(cfg), + tools_activity.CreateActivity_list_stargazers_for_repoTool(cfg), + tools_actions.CreateActions_delete_workflow_runTool(cfg), + tools_actions.CreateActions_get_workflow_runTool(cfg), + tools_actions.CreateActions_get_pending_deployments_for_runTool(cfg), + tools_actions.CreateActions_review_pending_deployments_for_runTool(cfg), + tools_actions.CreateActions_get_hosted_runners_machine_specs_for_orgTool(cfg), + tools_repos.CreateRepos_list_tagsTool(cfg), + tools_code_security.CreateCode_security_get_default_configurations_for_enterpriseTool(cfg), + tools_gists.CreateGists_list_for_userTool(cfg), + tools_apps.CreateApps_list_installation_requests_for_authenticated_appTool(cfg), + tools_repos.CreateRepos_list_deploy_keysTool(cfg), + tools_repos.CreateRepos_create_deploy_keyTool(cfg), + tools_orgs.CreateOrgs_revoke_org_role_userTool(cfg), + tools_orgs.CreateOrgs_assign_user_to_org_roleTool(cfg), + tools_code_scanning.CreateCode_scanning_create_variant_analysisTool(cfg), + tools_actions.CreateActions_add_selected_repo_to_org_secretTool(cfg), + tools_actions.CreateActions_remove_selected_repo_from_org_secretTool(cfg), + tools_issues.CreateIssues_list_events_for_timelineTool(cfg), + tools_pulls.CreatePulls_submit_reviewTool(cfg), + tools_teams.CreateTeams_list_projects_legacyTool(cfg), + tools_actions.CreateActions_get_org_public_keyTool(cfg), + tools_repos.CreateRepos_create_attestationTool(cfg), + tools_oidc.CreateOidc_get_oidc_custom_sub_template_for_orgTool(cfg), + tools_oidc.CreateOidc_update_oidc_custom_sub_template_for_orgTool(cfg), + tools_users.CreateUsers_list_following_for_userTool(cfg), + tools_orgs.CreateOrgs_list_webhook_deliveriesTool(cfg), + tools_teams.CreateTeams_remove_member_legacyTool(cfg), + tools_teams.CreateTeams_get_member_legacyTool(cfg), + tools_teams.CreateTeams_add_member_legacyTool(cfg), + tools_projects.CreateProjects_get_permission_for_userTool(cfg), + tools_repos.CreateRepos_get_community_profile_metricsTool(cfg), + tools_orgs.CreateOrgs_check_membership_for_userTool(cfg), + tools_orgs.CreateOrgs_remove_memberTool(cfg), + tools_git.CreateGit_create_tagTool(cfg), + tools_orgs.CreateOrgs_list_blocked_usersTool(cfg), + tools_security_advisories.CreateSecurity_advisories_get_repository_advisoryTool(cfg), + tools_security_advisories.CreateSecurity_advisories_update_repository_advisoryTool(cfg), + tools_apps.CreateApps_list_installationsTool(cfg), + tools_users.CreateUsers_list_public_ssh_keys_for_authenticated_userTool(cfg), + tools_users.CreateUsers_create_public_ssh_key_for_authenticated_userTool(cfg), + tools_users.CreateUsers_check_following_for_userTool(cfg), + tools_packages.CreatePackages_delete_package_for_authenticated_userTool(cfg), + tools_packages.CreatePackages_get_package_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_delete_release_assetTool(cfg), + tools_repos.CreateRepos_get_release_assetTool(cfg), + tools_repos.CreateRepos_update_release_assetTool(cfg), + tools_codespaces.CreateCodespaces_publish_for_authenticated_userTool(cfg), + tools_dependabot.CreateDependabot_set_repository_access_default_levelTool(cfg), + tools_dependabot.CreateDependabot_remove_selected_repo_from_org_secretTool(cfg), + tools_dependabot.CreateDependabot_add_selected_repo_to_org_secretTool(cfg), + tools_gists.CreateGists_createTool(cfg), + tools_gists.CreateGists_listTool(cfg), + tools_gists.CreateGists_list_commitsTool(cfg), + tools_code_scanning.CreateCode_scanning_get_variant_analysis_repo_taskTool(cfg), + tools_orgs.CreateOrgs_delete_attestations_by_idTool(cfg), + tools_codespaces.CreateCodespaces_list_repo_secretsTool(cfg), + tools_users.CreateUsers_list_followers_for_userTool(cfg), + tools_dependency_graph.CreateDependency_graph_export_sbomTool(cfg), + tools_actions.CreateActions_delete_self_hosted_runner_from_orgTool(cfg), + tools_actions.CreateActions_get_self_hosted_runner_for_orgTool(cfg), + tools_checks.CreateChecks_set_suites_preferencesTool(cfg), + tools_users.CreateUsers_list_public_emails_for_authenticated_userTool(cfg), + tools_apps.CreateApps_create_from_manifestTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_private_vulnerability_reportTool(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_repos.CreateRepos_delete_pull_request_review_protectionTool(cfg), + tools_repos.CreateRepos_get_pull_request_review_protectionTool(cfg), + tools_repos.CreateRepos_update_pull_request_review_protectionTool(cfg), + tools_teams.CreateTeams_delete_in_orgTool(cfg), + tools_teams.CreateTeams_get_by_nameTool(cfg), + tools_teams.CreateTeams_update_in_orgTool(cfg), + tools_orgs.CreateOrgs_get_webhook_config_for_orgTool(cfg), + tools_orgs.CreateOrgs_update_webhook_config_for_orgTool(cfg), + tools_gitignore.CreateGitignore_get_templateTool(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_repos.CreateRepos_get_repo_ruleset_historyTool(cfg), + tools_apps.CreateApps_remove_repo_from_installation_for_authenticated_userTool(cfg), + tools_apps.CreateApps_add_repo_to_installation_for_authenticated_userTool(cfg), + tools_actions.CreateActions_list_repo_organization_variablesTool(cfg), + tools_actions.CreateActions_delete_artifactTool(cfg), + tools_actions.CreateActions_get_artifactTool(cfg), + tools_actions.CreateActions_list_repo_organization_secretsTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_forkTool(cfg), + tools_checks.CreateChecks_create_suiteTool(cfg), + tools_actions.CreateActions_delete_actions_cache_by_idTool(cfg), + tools_code_scanning.CreateCode_scanning_get_alertTool(cfg), + tools_code_scanning.CreateCode_scanning_update_alertTool(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_security_advisories.CreateSecurity_advisories_list_org_repository_advisoriesTool(cfg), + tools_codespaces.CreateCodespaces_list_in_organizationTool(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_list_workflow_runsTool(cfg), + tools_issues.CreateIssues_list_labels_for_repoTool(cfg), + tools_issues.CreateIssues_create_labelTool(cfg), + tools_pulls.CreatePulls_check_if_mergedTool(cfg), + tools_pulls.CreatePulls_mergeTool(cfg), + tools_repos.CreateRepos_list_custom_deployment_rule_integrationsTool(cfg), + tools_repos.CreateRepos_list_contributorsTool(cfg), + tools_code_security.CreateCode_security_set_configuration_as_defaultTool(cfg), + tools_code_scanning.CreateCode_scanning_list_alert_instancesTool(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_classroom.CreateClassroom_list_classroomsTool(cfg), + tools_repos.CreateRepos_codeowners_errorsTool(cfg), + tools_activity.CreateActivity_mark_thread_as_doneTool(cfg), + tools_activity.CreateActivity_get_threadTool(cfg), + tools_activity.CreateActivity_mark_thread_as_readTool(cfg), + tools_billing.CreateBilling_get_github_actions_billing_userTool(cfg), + tools_issues.CreateIssues_list_for_authenticated_userTool(cfg), + tools_repos.CreateRepos_test_push_webhookTool(cfg), + tools_orgs.CreateOrgs_list_custom_properties_values_for_reposTool(cfg), + tools_orgs.CreateOrgs_create_or_update_custom_properties_values_for_reposTool(cfg), + tools_teams.CreateTeams_list_child_legacyTool(cfg), + tools_issues.CreateIssues_get_eventTool(cfg), + tools_repos.CreateRepos_list_teamsTool(cfg), + tools_repos.CreateRepos_delete_repo_rulesetTool(cfg), + tools_repos.CreateRepos_get_repo_rulesetTool(cfg), + tools_repos.CreateRepos_update_repo_rulesetTool(cfg), + tools_actions.CreateActions_get_workflowTool(cfg), + tools_billing.CreateBilling_get_github_packages_billing_orgTool(cfg), + tools_reactions.CreateReactions_create_for_releaseTool(cfg), + tools_reactions.CreateReactions_list_for_releaseTool(cfg), + tools_private_registries.CreatePrivate_registries_list_org_private_registriesTool(cfg), + tools_private_registries.CreatePrivate_registries_create_org_private_registryTool(cfg), + tools_actions.CreateActions_cancel_workflow_runTool(cfg), + tools_packages.CreatePackages_restore_package_version_for_orgTool(cfg), + tools_security_advisories.CreateSecurity_advisories_create_repository_advisory_cve_requestTool(cfg), + tools_reactions.CreateReactions_delete_for_issue_commentTool(cfg), + tools_repos.CreateRepos_get_all_deployment_protection_rulesTool(cfg), + tools_repos.CreateRepos_create_deployment_protection_ruleTool(cfg), + tools_code_security.CreateCode_security_get_default_configurationsTool(cfg), + tools_code_scanning.CreateCode_scanning_list_alerts_for_orgTool(cfg), + tools_issues.CreateIssues_list_eventsTool(cfg), + tools_apps.CreateApps_redeliver_webhook_deliveryTool(cfg), + tools_orgs.CreateOrgs_revoke_org_role_teamTool(cfg), + tools_orgs.CreateOrgs_assign_team_to_org_roleTool(cfg), + tools_repos.CreateRepos_list_deployment_branch_policiesTool(cfg), + tools_repos.CreateRepos_create_deployment_branch_policyTool(cfg), + tools_codespaces.CreateCodespaces_list_devcontainers_in_repository_for_authenticated_userTool(cfg), + tools_teams.CreateTeams_list_pending_invitations_in_orgTool(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_actions.CreateActions_list_repo_workflowsTool(cfg), + tools_issues.CreateIssues_get_labelTool(cfg), + tools_issues.CreateIssues_update_labelTool(cfg), + tools_issues.CreateIssues_delete_labelTool(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_projects.CreateProjects_list_cardsTool(cfg), + tools_projects.CreateProjects_create_cardTool(cfg), + tools_repos.CreateRepos_transferTool(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_private_registries.CreatePrivate_registries_get_org_public_keyTool(cfg), + tools_billing.CreateBilling_get_github_packages_billing_userTool(cfg), + tools_apps.CreateApps_scope_tokenTool(cfg), + tools_orgs.CreateOrgs_delete_attestations_bulkTool(cfg), + tools_issues.CreateIssues_get_milestoneTool(cfg), + tools_issues.CreateIssues_update_milestoneTool(cfg), + tools_issues.CreateIssues_delete_milestoneTool(cfg), + tools_secret_scanning.CreateSecret_scanning_list_alerts_for_orgTool(cfg), + tools_security_advisories.CreateSecurity_advisories_list_global_advisoriesTool(cfg), + tools_migrations.CreateMigrations_get_large_filesTool(cfg), + tools_users.CreateUsers_delete_attestations_by_subject_digestTool(cfg), + tools_issues.CreateIssues_list_sub_issuesTool(cfg), + tools_issues.CreateIssues_add_sub_issueTool(cfg), + tools_activity.CreateActivity_list_repo_eventsTool(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_git.CreateGit_create_blobTool(cfg), + tools_actions.CreateActions_disable_selected_repository_github_actions_organizationTool(cfg), + tools_actions.CreateActions_enable_selected_repository_github_actions_organizationTool(cfg), + tools_dependabot.CreateDependabot_list_org_secretsTool(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_code_scanning.CreateCode_scanning_upload_sarifTool(cfg), + tools_actions.CreateActions_list_artifacts_for_repoTool(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..91f090b --- /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.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`.")), + 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`")), + ) + + 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..e135fab --- /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("key_id", mcp.Required(), mcp.Description("Input parameter: ID of the key you used to encrypt 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.")), + ) + + 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..e503d84 --- /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("value", mcp.Required(), mcp.Description("Input parameter: The value of the variable.")), + 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`.")), + ) + + 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..45b53b8 --- /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.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.")), + 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.")), + ) + + 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..9c918df --- /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.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.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the new runner.")), + ) + + 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..8072516 --- /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.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_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..745d6df --- /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.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")), + mcp.WithArray("environment_ids", mcp.Required(), mcp.Description("Input parameter: The list of environment ids to approve or reject")), + ) + + 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..0b5fedc --- /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.WithArray("include_claim_keys", mcp.Description("Input parameter: Array of unique strings. Each claim key can only contain alphanumeric characters and underscores.")), + 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.")), + ) + + 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..d24256e --- /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.WithBoolean("enabled", mcp.Required(), mcp.Description("Input parameter: Whether GitHub Actions is enabled on the repository.")), + mcp.WithString("allowed_actions", mcp.Description("Input parameter: The permissions policy that controls the actions and reusable workflows that are allowed to run.")), + ) + + 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..45930b0 --- /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("value", mcp.Description("Input parameter: The value of the variable.")), + mcp.WithString("name", mcp.Description("Input parameter: The name 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..509d453 --- /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("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.")), + 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.")), + ) + + 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..21604e6 --- /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("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.")), + 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`.")), + ) + + 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..f4f3dd1 --- /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.WithBoolean("read", mcp.Description("Input parameter: Whether the notification has been 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.")), + ) + + 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..fcaafaa --- /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("repositories", mcp.Description("Input parameter: List of repository names that the token should have access to")), + 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.")), + ) + + 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..5689fc8 --- /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("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.")), + 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.")), + ) + + 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..b888193 --- /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.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.")), + 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.")), + ) + + 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..b1190fe --- /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("head_sha", mcp.Required(), mcp.Description("Input parameter: The SHA of the commit.")), + 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.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.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("name", mcp.Required(), mcp.Description("Input parameter: The name of the check. For example, \"code-coverage\".")), + 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`.")), + 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.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`.")), + ) + + 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..83dfd51 --- /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.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("name", mcp.Description("Input parameter: The name of the check. For example, \"code-coverage\".")), + 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.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("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.")), + mcp.WithString("external_id", mcp.Description("Input parameter: A reference for the run on the integrator's system.")), + 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("status", mcp.Description("Input parameter: The current status of the check run. Only GitHub Actions can set a status of `waiting`, `pending`, or `requested`.")), + ) + + 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..f1cc005 --- /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_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.")), + 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.")), + ) + + 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..3f6cca5 --- /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.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`.")), + 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.")), + ) + + 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..fc31229 --- /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.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.")), + 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.")), + ) + + 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..84eea0a --- /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("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.")), + 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`.")), + ) + + 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..8fb3f3d --- /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_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + mcp.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the code security configuration. Must be unique within the organization.")), + mcp.WithString("private_vulnerability_reporting", mcp.Description("Input parameter: The enablement status of private vulnerability reporting")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non provider patterns")), + 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_delegated_bypass", mcp.Description("Input parameter: The enablement status of secret scanning delegated bypass")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + 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("description", mcp.Required(), mcp.Description("Input parameter: A description of the code security configuration")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement status for a security configuration")), + mcp.WithObject("secret_scanning_delegated_bypass_options", mcp.Description("Input parameter: Feature options for secret scanning delegated bypass")), + 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("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("code_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of code scanning delegated alert dismissal")), + mcp.WithString("dependency_graph", mcp.Description("Input parameter: The enablement status of Dependency Graph")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithString("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + ) + + 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..fd7b56d --- /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("name", mcp.Required(), mcp.Description("Input parameter: The name of the code security configuration. Must be unique within the enterprise.")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non provider patterns")), + 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("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("code_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of code scanning delegated alert dismissal")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + mcp.WithString("description", mcp.Required(), mcp.Description("Input parameter: A description of the code security configuration")), + mcp.WithString("code_scanning_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of 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("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + 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_generic_secrets", mcp.Description("Input parameter: The enablement status of Copilot secret scanning")), + mcp.WithString("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + 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.")), + ) + + 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..bde0053 --- /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("secret_scanning_push_protection", mcp.Description("Input parameter: The enablement status of secret scanning push protection")), + mcp.WithString("enforcement", mcp.Description("Input parameter: The enforcement status for a security configuration")), + mcp.WithString("description", mcp.Description("Input parameter: A description of the code 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_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("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("secret_scanning_delegated_bypass", mcp.Description("Input parameter: The enablement status of secret scanning delegated bypass")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the code security configuration. Must be unique within the organization.")), + mcp.WithString("private_vulnerability_reporting", mcp.Description("Input parameter: The enablement status of private vulnerability reporting")), + mcp.WithString("secret_scanning_generic_secrets", mcp.Description("Input parameter: The enablement status of Copilot secret scanning")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithString("dependabot_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + 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.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithObject("secret_scanning_delegated_bypass_options", mcp.Description("Input parameter: Feature options for secret scanning delegated bypass")), + 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")), + ) + + 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..8ce8d1a --- /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("dependency_graph", mcp.Description("Input parameter: The enablement status of Dependency Graph")), + 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("secret_scanning_delegated_alert_dismissal", mcp.Description("Input parameter: The enablement status of secret scanning delegated alert dismissal")), + mcp.WithString("secret_scanning_push_protection", mcp.Description("Input parameter: The enablement status of secret scanning push protection")), + mcp.WithObject("code_scanning_default_setup_options", mcp.Description("Input parameter: Feature options for code scanning default setup")), + mcp.WithString("description", mcp.Description("Input parameter: A description of the code security configuration")), + 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("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_alerts", mcp.Description("Input parameter: The enablement status of Dependabot alerts")), + mcp.WithString("dependabot_security_updates", mcp.Description("Input parameter: The enablement status of Dependabot security updates")), + mcp.WithString("dependency_graph_autosubmit_action", mcp.Description("Input parameter: The enablement status of Automatic dependency submission")), + mcp.WithString("secret_scanning_validity_checks", mcp.Description("Input parameter: The enablement status of secret scanning validity checks")), + mcp.WithString("code_scanning_default_setup", mcp.Description("Input parameter: The enablement status of code scanning default setup")), + mcp.WithObject("dependency_graph_autosubmit_action_options", mcp.Description("Input parameter: Feature options for Automatic dependency submission")), + mcp.WithString("name", mcp.Description("Input parameter: The name of the code security configuration. Must be unique across the enterprise.")), + mcp.WithString("secret_scanning", mcp.Description("Input parameter: The enablement status of secret scanning")), + mcp.WithString("secret_scanning_non_provider_patterns", mcp.Description("Input parameter: The enablement status of secret scanning non-provider patterns")), + ) + + 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..7282430 --- /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.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.")), + 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.")), + ) + + 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..0447af3 --- /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("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.")), + 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.")), + ) + + 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..ad030db --- /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.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.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.WithNumber("idle_timeout_minutes", mcp.Description("Input parameter: Time in minutes before codespace stops from inactivity")), + 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.WithString("working_directory", mcp.Description("Input parameter: Working directory for this codespace")), + 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")), + ) + + 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..c0279d1 --- /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("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("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.WithBoolean("multi_repo_permissions_opt_out", mcp.Description("Input parameter: Whether to authorize requested permissions from devcontainer.json")), + mcp.WithString("devcontainer_path", mcp.Description("Input parameter: Path to devcontainer.json config to use for this codespace")), + mcp.WithNumber("idle_timeout_minutes", mcp.Description("Input parameter: Time in minutes before codespace stops from inactivity")), + mcp.WithString("machine", mcp.Description("Input parameter: Machine type to use for this codespace")), + mcp.WithString("ref", mcp.Description("Input parameter: Git ref (typically a branch name) for this codespace")), + mcp.WithString("client_ip", mcp.Description("Input parameter: IP for location auto-detection when proxying a request")), + mcp.WithString("working_directory", mcp.Description("Input parameter: Working directory for this codespace")), + 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).")), + ) + + 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..20248cf --- /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.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.")), + 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.")), + ) + + 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..4af4a02 --- /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("display_name", mcp.Description("Input parameter: Display name for this 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.")), + ) + + 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..189a19e --- /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.WithString("key_id", 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/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.")), + ) + + 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..6d3e507 --- /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("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.")), + 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_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..120e4f0 --- /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_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`.")), + mcp.WithString("dismissed_comment", mcp.Description("Input parameter: An optional comment associated with dismissing the alert.")), + ) + + 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..60123a2 --- /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("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.")), + 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.")), + ) + + 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..75a72da --- /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.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.")), + 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.")), + ) + + 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..0f349a3 --- /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("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.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The SHA1 value for this reference.")), + ) + + 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..9b1d7ae --- /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("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.")), + mcp.WithString("object", mcp.Required(), mcp.Description("Input parameter: The SHA of the git object this is tagging.")), + ) + + 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..09fc278 --- /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.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.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The SHA1 value to set this reference to")), + ) + + 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..91a6a1d --- /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("compute_service", mcp.Description("Input parameter: The hosted compute service to use for the network configuration.")), + 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.")), + ) + + 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..7b7b3b3 --- /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("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.")), + 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._")), + ) + + 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..2a21ff4 --- /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("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.")), + 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).\"")), + ) + + 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..f9d366e --- /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("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")), + 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).")), + ) + + 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..09361d8 --- /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("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("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.WithString("body", mcp.Description("Input parameter: The contents of the issue.")), + mcp.WithString("state_reason", mcp.Description("Input parameter: The reason for the state change. Ignored unless `state` is changed.")), + mcp.WithString("assignee", mcp.Description("Input parameter: Username to assign to this issue. **This field is closing down.**")), + 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.")), + mcp.WithString("milestone", mcp.Description("")), + mcp.WithString("state", mcp.Description("Input parameter: The open or closed state of the issue.")), + ) + + 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..eeb52e2 --- /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("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.")), + 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).\"")), + ) + + 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..11d3b67 --- /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("title", mcp.Description("Input parameter: The title of 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`.")), + ) + + 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..ee20e70 --- /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("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_git_data", mcp.Description("Input parameter: Indicates whether the repository git data should be excluded from the migration.")), + mcp.WithBoolean("exclude_releases", mcp.Description("Input parameter: Do not include releases in the migration")), + 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_owner_projects", mcp.Description("Input parameter: Indicates whether projects owned by the organization or users should be excluded.")), + ) + + 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..b3bb0f2 --- /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_metadata", mcp.Description("Input parameter: Indicates whether metadata should be excluded and only git source should be included for 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("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.WithArray("repositories", mcp.Required(), mcp.Description("Input parameter: A list of arrays indicating which repositories should be migrated.")), + mcp.WithBoolean("exclude_git_data", mcp.Description("Input parameter: Indicates whether the repository git data should be excluded from 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).")), + mcp.WithBoolean("lock_repositories", mcp.Description("Input parameter: Indicates whether repositories should be locked (to prevent manipulation) while migrating data.")), + 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("exclude_attachments", mcp.Description("Input parameter: Indicates whether attachments 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..ce6908f --- /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("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 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.")), + ) + + 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..d28a4d6 --- /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("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")), + 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")), + ) + + 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..f5b5f83 --- /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.WithString("name", mcp.Required(), mcp.Description("Input parameter: Must be passed as \"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.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.")), + ) + + 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..87a41f1 --- /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("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.WithString("location", mcp.Description("Input parameter: The location.")), + 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("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.WithBoolean("has_repository_projects", mcp.Description("Input parameter: Whether repositories that belong to the organization can use repository projects.")), + 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.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("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("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_fork_private_repositories", mcp.Description("Input parameter: Whether organization members can fork private organization repositories.")), + mcp.WithString("blog", mcp.Description("")), + mcp.WithString("default_repository_permission", mcp.Description("Input parameter: Default permission level members have for organization repositories.")), + 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.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.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.WithBoolean("has_organization_projects", mcp.Description("Input parameter: Whether an organization can use organization projects.")), + 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("email", mcp.Description("Input parameter: The publicly visible email address.")), + 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.")), + 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.WithString("name", mcp.Description("Input parameter: The shorthand name of the company.")), + 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("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.WithString("billing_email", mcp.Description("Input parameter: Billing email address. This address is not publicized.")), + 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("description", mcp.Description("Input parameter: The description of the company. The maximum size is 160 characters.")), + 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("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.WithString("twitter_username", mcp.Description("Input parameter: The Twitter username of the company.")), + mcp.WithString("company", mcp.Description("Input parameter: The company name.")), + ) + + 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..6776400 --- /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.WithString("action", mcp.Required(), mcp.Description("Input parameter: Action to apply to the fine-grained personal access token.")), + mcp.WithArray("pat_ids", mcp.Required(), mcp.Description("Input parameter: The IDs of the fine-grained personal access tokens.")), + ) + + 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..002b065 --- /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.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.")), + 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("")), + ) + + 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..f0346ce --- /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("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: 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..b53bd00 --- /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("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`.")), + 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.")), + ) + + 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..fff8f8d --- /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("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`.")), + mcp.WithString("url", mcp.Description("Input parameter: The URL of the private registry.")), + ) + + 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..eaa24b8 --- /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("name", mcp.Required(), mcp.Description("Input parameter: Name of the project")), + mcp.WithString("body", mcp.Description("Input parameter: Body 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..96d1e70 --- /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("name", mcp.Required(), mcp.Description("Input parameter: The name of the project.")), + mcp.WithString("body", mcp.Description("Input parameter: The description 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..4f3eaec --- /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.WithNumber("column_id", mcp.Description("Input parameter: The unique identifier of the column the card should be moved to")), + 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.")), + ) + + 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..33dc70c --- /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.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")), + 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")), + ) + + 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..504acbd --- /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.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.")), + 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.")), + ) + + 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..90e88d7 --- /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.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.")), + 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.WithString("path", mcp.Required(), mcp.Description("Input parameter: The relative path to the file that necessitates a comment.")), + mcp.WithString("subject_type", mcp.Description("Input parameter: The level at which the comment is targeted.")), + 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("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.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("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("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.")), + ) + + 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..ad8e06f --- /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("message", mcp.Required(), mcp.Description("Input parameter: The message for the pull request review dismissal")), + mcp.WithString("event", mcp.Description("")), + ) + + 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..85010b4 --- /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.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.")), + 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`.")), + ) + + 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..0063ae9 --- /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.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`.")), + 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.")), + ) + + 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..2e796d2 --- /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.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.")), + mcp.WithString("path", mcp.Description("Input parameter: Relative path of 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..bc94422 --- /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.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.")), + mcp.WithString("key", mcp.Required(), mcp.Description("Input parameter: The contents of 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..3d63049 --- /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.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("environment", mcp.Description("Input parameter: Name for the target deployment environment (e.g., `production`, `staging`, `qa`).")), + 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.WithString("task", mcp.Description("Input parameter: Specifies a task to execute (e.g., `deploy` or `deploy:migrations`).")), + mcp.WithString("description", mcp.Description("Input parameter: Short description of the deployment.")), + 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("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.")), + ) + + 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..0b79147 --- /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("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).")), + mcp.WithString("type", mcp.Description("Input parameter: Whether this rule targets a branch or tag")), + ) + + 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..72eab3a --- /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.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`.")), + 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.")), + ) + + 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..a9d056d --- /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.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.")), + mcp.WithString("event_type", mcp.Required(), mcp.Description("Input parameter: A custom webhook event name. Must be 100 characters or fewer.")), + ) + + 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..2fa7d6c --- /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("has_issues", mcp.Description("Input parameter: Whether issues are enabled.")), + mcp.WithString("homepage", mcp.Description("Input parameter: A URL with more information about the repository.")), + mcp.WithBoolean("private", mcp.Description("Input parameter: Whether the repository is private.")), + mcp.WithBoolean("has_downloads", mcp.Description("Input parameter: Whether downloads are enabled.")), + 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: Whether to allow merge commits for pull requests.")), + mcp.WithBoolean("allow_squash_merge", mcp.Description("Input parameter: Whether to allow squash merges for pull requests.")), + mcp.WithString("gitignore_template", mcp.Description("Input parameter: The desired language or platform to apply to the .gitignore.")), + 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.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("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.WithBoolean("allow_auto_merge", mcp.Description("Input parameter: Whether to allow Auto-merge to be used on pull requests.")), + mcp.WithBoolean("delete_branch_on_merge", mcp.Description("Input parameter: Whether to delete head branches when pull requests are merged")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the repository.")), + mcp.WithBoolean("has_discussions", mcp.Description("Input parameter: Whether discussions are enabled.")), + mcp.WithBoolean("is_template", mcp.Description("Input parameter: Whether this repository acts as a template that can be used to generate new repositories.")), + mcp.WithString("license_template", mcp.Description("Input parameter: The license keyword of the open source license for this repository.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the repository.")), + 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("has_projects", mcp.Description("Input parameter: Whether projects are enabled.")), + mcp.WithBoolean("auto_init", mcp.Description("Input parameter: Whether the repository is initialized with a minimal README.")), + mcp.WithBoolean("has_wiki", mcp.Description("Input parameter: Whether the wiki is enabled.")), + mcp.WithBoolean("allow_rebase_merge", mcp.Description("Input parameter: Whether to allow rebase merges for pull requests.")), + ) + + 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..0eeca8b --- /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.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.")), + mcp.WithBoolean("default_branch_only", mcp.Description("Input parameter: When forking from an existing repository, fork with only the default branch.")), + ) + + 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..7a7752a --- /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.WithBoolean("has_issues", mcp.Description("Input parameter: Either `true` to enable issues for this repository or `false` to disable them.")), + 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.WithBoolean("has_downloads", mcp.Description("Input parameter: Whether downloads 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.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\".")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name of the repository.")), + mcp.WithBoolean("allow_rebase_merge", mcp.Description("Input parameter: Either `true` to allow rebase-merging pull requests, or `false` to prevent rebase-merging.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description of the repository.")), + mcp.WithString("visibility", mcp.Description("Input parameter: The visibility of the repository.")), + 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.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.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: Either `true` to enable the wiki for this repository or `false` to disable it.")), + 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.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.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("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.WithBoolean("private", mcp.Description("Input parameter: Whether the repository is private.")), + mcp.WithString("homepage", mcp.Description("Input parameter: A URL with more information about the repository.")), + 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("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("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("auto_init", mcp.Description("Input parameter: Pass `true` to create an initial commit with empty README.")), + ) + + 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..d75db1a --- /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.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.")), + 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).")), + ) + + 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..67df8aa --- /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.WithString("sha", mcp.Description("Input parameter: **Required if you are updating a file**. The blob SHA of the file being replaced.")), + 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.")), + ) + + 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..c30c916 --- /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("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`.")), + 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).")), + ) + + 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..d28a056 --- /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("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.")), + 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.")), + ) + + 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..1eb9e07 --- /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("name", mcp.Description("Input parameter: The name of the release.")), + mcp.WithString("tag_name", mcp.Required(), mcp.Description("Input parameter: The name of the tag.")), + mcp.WithBoolean("draft", mcp.Description("Input parameter: `true` to create a draft (unpublished) release, `false` to create a published one.")), + 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("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.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.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.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.")), + ) + + 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..d38f43e --- /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.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")), + 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")), + ) + + 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..80b2e51 --- /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("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.")), + 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.")), + ) + + 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..52e621f --- /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.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.")), + mcp.WithString("sha", mcp.Required(), mcp.Description("Input parameter: The blob SHA of the file being deleted.")), + ) + + 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..67a0528 --- /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("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.")), + 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.")), + ) + + 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..641e58b --- /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("archived", mcp.Description("Input parameter: Whether to archive this repository. `false` will unarchive a previously archived repository.")), + mcp.WithBoolean("has_issues", mcp.Description("Input parameter: Either `true` to enable issues for this repository or `false` to disable them.")), + 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.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("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("is_template", mcp.Description("Input parameter: Either `true` to make this repo available as a template repository or `false` to prevent it.")), + 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.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_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("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_forking", mcp.Description("Input parameter: Either `true` to allow private forks, or `false` to prevent private forks.")), + 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("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.WithString("default_branch", mcp.Description("Input parameter: Updates the default branch for this 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.")), + mcp.WithString("description", mcp.Description("Input parameter: A short description 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.WithString("visibility", mcp.Description("Input parameter: The visibility of the repository.")), + 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_squash_merge", mcp.Description("Input parameter: Either `true` to allow squash-merging pull requests, or `false` to prevent squash-merging.")), + mcp.WithString("homepage", mcp.Description("Input parameter: A URL with more information about 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.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.WithString("name", mcp.Description("Input parameter: The name of the repository.")), + ) + + 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..71596da --- /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.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.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.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.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_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("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("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("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("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.")), + 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.")), + ) + + 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..ae62b6d --- /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.WithBoolean("https_enforced", mcp.Description("Input parameter: Specify whether HTTPS should be enforced for the repository.")), + mcp.WithString("source", mcp.Description("")), + 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).\"")), + ) + + 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..14b8340 --- /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.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.")), + 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.")), + ) + + 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..6d5f7fd --- /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("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.")), + 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.")), + ) + + 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..e429517 --- /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("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.")), + mcp.WithString("state", mcp.Description("")), + ) + + 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..3989883 --- /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.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")), + 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.")), + ) + + 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..c283622 --- /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("checks", mcp.Description("Input parameter: The list of status checks to require in order to merge into this branch.")), + 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.")), + ) + + 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..793078c --- /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.WithBoolean("active", mcp.Description("Input parameter: Determines if notifications are sent when the webhook is triggered. Set to `true` to send notifications.")), + 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.")), + ) + + 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..2c3e677 --- /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("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: 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..a47d9ed --- /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("reason", mcp.Required(), mcp.Description("Input parameter: The reason for bypassing push protection.")), + 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.")), + ) + + 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..091d57b --- /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.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.")), + 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`.")), + ) + + 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..24057da --- /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("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("summary", mcp.Required(), mcp.Description("Input parameter: A short summary of the advisory.")), + 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.")), + 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.WithArray("vulnerabilities", mcp.Required(), mcp.Description("Input parameter: A product affected by the vulnerability detailed in a repository 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..1d2b0c5 --- /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("credits", mcp.Description("Input parameter: A list of users receiving credit for their participation in the security advisory.")), + mcp.WithString("description", mcp.Description("Input parameter: A detailed description of what the advisory impacts.")), + mcp.WithArray("cwe_ids", mcp.Description("Input parameter: A list of Common Weakness Enumeration (CWE) IDs.")), + mcp.WithString("severity", mcp.Description("Input parameter: The severity of the advisory. You must choose between setting this field or `cvss_vector_string`.")), + mcp.WithArray("vulnerabilities", mcp.Description("Input parameter: A product affected by the vulnerability detailed in a repository security advisory.")), + mcp.WithArray("collaborating_teams", mcp.Description("Input parameter: A list of team slugs which have been granted write access to the advisory.")), + mcp.WithString("state", mcp.Description("Input parameter: The state of the advisory.")), + 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("summary", mcp.Description("Input parameter: A short summary of the advisory.")), + mcp.WithArray("collaborating_users", mcp.Description("Input parameter: A list of usernames who have been granted write access to the advisory.")), + ) + + 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..0de007d --- /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.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.")), + 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.")), + ) + + 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..acea459 --- /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("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_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..e080f44 --- /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("body", mcp.Description("Input parameter: The discussion post's body text.")), + mcp.WithString("title", mcp.Description("Input parameter: The discussion post's title.")), + ) + + 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..e367925 --- /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("body", mcp.Description("Input parameter: The discussion post's body text.")), + mcp.WithString("title", mcp.Description("Input parameter: The discussion post's title.")), + ) + + 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..b9fb3c5 --- /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.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.")), + 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.")), + ) + + 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..4b964a7 --- /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("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.")), + mcp.WithString("name", mcp.Required(), mcp.Description("Input parameter: The name 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..3ac31b4 --- /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("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.")), + 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.")), + ) + + return models.Tool{ + Definition: tool, + Handler: Users_update_authenticatedHandler(cfg), + } +}