| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268 |
- /**
- * MCP Server Setup
- * Contains all the server configuration, tool schemas, and request handlers
- */
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
- import {
- CallToolRequestSchema,
- ListToolsRequestSchema,
- ListResourcesRequestSchema,
- ReadResourceRequestSchema,
- } from '@modelcontextprotocol/sdk/types.js';
- import { z } from 'zod';
- import { GogsClient } from './gogs-client.js';
- // Define tool schemas
- const GetUserSchema = z.object({
- username: z.string().describe('Username to get information for'),
- });
- const SearchUsersSchema = z.object({
- query: z.string().describe('Search query for users'),
- limit: z.number().optional().describe('Maximum number of results (default: 10)'),
- });
- const ListUserReposSchema = z.object({
- username: z.string().optional().describe('Username (omit for authenticated user)'),
- });
- const SearchReposSchema = z.object({
- query: z.string().describe('Search query for repositories'),
- uid: z.number().optional().describe('User ID to filter repositories'),
- limit: z.number().optional().describe('Maximum number of results (default: 10)'),
- page: z.number().optional().describe('Page number (default: 1)'),
- });
- const GetRepoSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const CreateRepoSchema = z.object({
- name: z.string().describe('Repository name'),
- description: z.string().optional().describe('Repository description'),
- private: z.boolean().optional().describe('Create as private repository (default: false)'),
- auto_init: z.boolean().optional().describe('Initialize with README (default: false)'),
- gitignores: z.string().optional().describe('Gitignore templates (e.g., "Go,VisualStudioCode")'),
- license: z.string().optional().describe('License template (e.g., "MIT License")'),
- readme: z.string().optional().describe('README template (default: "Default")'),
- });
- const DeleteRepoSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const GetContentsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- path: z.string().describe('File or directory path'),
- ref: z.string().optional().describe('Branch, tag, or commit SHA (default: default branch)'),
- });
- const GetRawContentSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- ref: z.string().describe('Branch, tag, or commit SHA'),
- path: z.string().describe('File path'),
- });
- const ListBranchesSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const GetCommitsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- sha: z.string().optional().describe('Branch name or commit SHA'),
- page: z.number().optional().describe('Page number (default: 1)'),
- });
- const GetTreeSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- sha: z.string().describe('Git tree SHA or commit SHA'),
- });
- const ListIssuesSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- state: z.enum(['open', 'closed', 'all']).optional().describe('Filter by state (default: open)'),
- labels: z.string().optional().describe('Comma-separated list of label names'),
- page: z.number().optional().describe('Page number (default: 1)'),
- per_page: z.number().optional().describe('Results per page (default: 30)'),
- });
- const GetIssueSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- });
- const CreateIssueSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- title: z.string().describe('Issue title'),
- body: z.string().optional().describe('Issue description'),
- assignee: z.string().optional().describe('Username to assign the issue to'),
- milestone: z.number().optional().describe('Milestone ID'),
- labels: z.array(z.number()).optional().describe('Array of label IDs'),
- });
- const UpdateIssueSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- title: z.string().optional().describe('Issue title'),
- body: z.string().optional().describe('Issue description'),
- assignee: z.string().optional().describe('Username to assign the issue to'),
- milestone: z.number().optional().describe('Milestone ID'),
- state: z.enum(['open', 'closed']).optional().describe('Issue state'),
- labels: z.array(z.number()).optional().describe('Array of label IDs'),
- });
- const ListIssueCommentsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- });
- const CreateIssueCommentSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- body: z.string().describe('Comment text'),
- });
- const UpdateIssueCommentSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- commentId: z.number().describe('Comment ID'),
- body: z.string().describe('Updated comment text'),
- });
- const ListLabelsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const GetLabelSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- labelId: z.number().describe('Label ID'),
- });
- const CreateLabelSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- name: z.string().describe('Label name'),
- color: z.string().describe('7-character hex color code with leading # (e.g., #ff0000)'),
- });
- const UpdateLabelSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- labelId: z.number().describe('Label ID'),
- name: z.string().optional().describe('Label name'),
- color: z.string().optional().describe('7-character hex color code with leading # (e.g., #ff0000)'),
- });
- const DeleteLabelSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- labelId: z.number().describe('Label ID'),
- });
- const ListIssueLabelsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- });
- const AddIssueLabelsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- labels: z.array(z.number()).describe('Array of label IDs to add'),
- });
- const RemoveIssueLabelSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- labelId: z.number().describe('Label ID to remove'),
- });
- const ReplaceIssueLabelsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- labels: z.array(z.number()).describe('Array of label IDs to set (replaces all existing labels)'),
- });
- const RemoveAllIssueLabelsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- number: z.number().describe('Issue number'),
- });
- const ListMilestonesSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const GetMilestoneSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- milestoneId: z.number().describe('Milestone ID'),
- });
- const CreateMilestoneSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- title: z.string().describe('Milestone title'),
- description: z.string().optional().describe('Milestone description'),
- due_on: z.string().optional().describe('Due date in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)'),
- });
- const UpdateMilestoneSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- milestoneId: z.number().describe('Milestone ID'),
- title: z.string().optional().describe('Milestone title'),
- description: z.string().optional().describe('Milestone description'),
- due_on: z.string().optional().describe('Due date in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)'),
- state: z.enum(['open', 'closed']).optional().describe('Milestone state'),
- });
- const DeleteMilestoneSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- milestoneId: z.number().describe('Milestone ID'),
- });
- const CreateOrganizationSchema = z.object({
- username: z.string().describe('Organization username (alphanumeric, dashes, underscores)'),
- full_name: z.string().optional().describe('Organization full name'),
- description: z.string().optional().describe('Organization description'),
- website: z.string().optional().describe('Organization website'),
- location: z.string().optional().describe('Organization location'),
- });
- const ListPublicOrganizationsSchema = z.object({
- username: z.string().describe('Username to get public organizations for'),
- });
- const GetOrganizationSchema = z.object({
- orgname: z.string().describe('Organization name'),
- });
- const UpdateOrganizationSchema = z.object({
- orgname: z.string().describe('Organization name'),
- full_name: z.string().optional().describe('Organization full name'),
- description: z.string().optional().describe('Organization description'),
- website: z.string().optional().describe('Organization website'),
- location: z.string().optional().describe('Organization location'),
- });
- const AddOrganizationMemberSchema = z.object({
- orgname: z.string().describe('Organization name'),
- username: z.string().describe('Username to add as member'),
- role: z.enum(['admin', 'member']).describe('Member role (admin or member)'),
- });
- const ListOrganizationTeamsSchema = z.object({
- orgname: z.string().describe('Organization name'),
- });
- const CreateTeamSchema = z.object({
- orgname: z.string().describe('Organization name'),
- name: z.string().describe('Team name (max 30 characters, alphanumeric with dashes and dots)'),
- description: z.string().optional().describe('Team description (max 255 characters)'),
- permission: z.enum(['read', 'write', 'admin']).optional().describe('Team permission level (default: read)'),
- });
- const GetTeamSchema = z.object({
- teamId: z.number().describe('Team ID'),
- });
- const AddTeamMemberSchema = z.object({
- teamId: z.number().describe('Team ID'),
- username: z.string().describe('Username to add to the team'),
- });
- const RemoveTeamMemberSchema = z.object({
- teamId: z.number().describe('Team ID'),
- username: z.string().describe('Username to remove from the team'),
- });
- const ListReleasesSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const ListCollaboratorsSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const CheckCollaboratorSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- username: z.string().describe('Username to check for collaborator status'),
- });
- const AddCollaboratorSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- username: z.string().describe('Username to add as collaborator'),
- permission: z.enum(['read', 'write', 'admin']).optional().describe('Permission level (default: write)'),
- });
- const RemoveCollaboratorSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- username: z.string().describe('Username to remove as collaborator'),
- });
- const AddUserEmailsSchema = z.object({
- emails: z.array(z.string()).describe('Array of email addresses to add'),
- });
- const DeleteUserEmailsSchema = z.object({
- emails: z.array(z.string()).describe('Array of email addresses to delete'),
- });
- const ListUserKeysSchema = z.object({
- username: z.string().describe('Username to list public keys for'),
- });
- const GetPublicKeySchema = z.object({
- keyId: z.number().describe('Public key ID'),
- });
- const CreatePublicKeySchema = z.object({
- title: z.string().describe('Key title/name for identification'),
- key: z.string().describe('The public key content (SSH public key format)'),
- });
- const DeletePublicKeySchema = z.object({
- keyId: z.number().describe('Public key ID to delete'),
- });
- const ListHooksSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const CreateHookSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- type: z.enum(['gogs', 'slack']).describe('Webhook type (gogs or slack)'),
- config: z.object({
- url: z.string().describe('URL to send webhook payloads to'),
- content_type: z.enum(['json', 'form']).describe('Content type for payload (json or form)'),
- secret: z.string().optional().describe('Optional secret for webhook validation'),
- channel: z.string().optional().describe('Slack channel (for slack webhooks)'),
- username: z.string().optional().describe('Slack username (for slack webhooks)'),
- icon_url: z.string().optional().describe('Slack icon URL (for slack webhooks)'),
- color: z.string().optional().describe('Slack color (for slack webhooks)'),
- }).describe('Webhook configuration'),
- events: z.array(z.enum(['create', 'delete', 'fork', 'push', 'issues', 'issue_comment', 'pull_request', 'release']))
- .optional()
- .describe('Events that trigger the webhook (default: ["push"])'),
- active: z.boolean().optional().describe('Whether the webhook is active (default: false)'),
- });
- const UpdateHookSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- hookId: z.number().describe('Webhook ID to update'),
- config: z.object({
- url: z.string().describe('URL to send webhook payloads to'),
- content_type: z.enum(['json', 'form']).describe('Content type for payload (json or form)'),
- secret: z.string().optional().describe('Optional secret for webhook validation'),
- channel: z.string().optional().describe('Slack channel (for slack webhooks)'),
- username: z.string().optional().describe('Slack username (for slack webhooks)'),
- icon_url: z.string().optional().describe('Slack icon URL (for slack webhooks)'),
- color: z.string().optional().describe('Slack color (for slack webhooks)'),
- }).describe('Webhook configuration'),
- events: z.array(z.enum(['create', 'delete', 'fork', 'push', 'issues', 'issue_comment', 'pull_request', 'release']))
- .optional()
- .describe('Events that trigger the webhook'),
- active: z.boolean().optional().describe('Whether the webhook is active'),
- });
- const DeleteHookSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- hookId: z.number().describe('Webhook ID to delete'),
- });
- const ListFollowersSchema = z.object({
- username: z.string().describe('Username to list followers for'),
- });
- const ListFollowingSchema = z.object({
- username: z.string().describe('Username to list following for'),
- });
- const CheckFollowingSchema = z.object({
- username: z.string().describe('Username to check if authenticated user is following'),
- });
- const FollowUserSchema = z.object({
- username: z.string().describe('Username to follow'),
- });
- const UnfollowUserSchema = z.object({
- username: z.string().describe('Username to unfollow'),
- });
- const ListDeployKeysSchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- });
- const GetDeployKeySchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- keyId: z.number().describe('Deploy key ID'),
- });
- const CreateDeployKeySchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- title: z.string().describe('Deploy key title/name for identification'),
- key: z.string().describe('The public key content (SSH public key format)'),
- read_only: z.boolean().optional().describe('Whether the key is read-only (default: true)'),
- });
- const DeleteDeployKeySchema = z.object({
- owner: z.string().describe('Repository owner username'),
- repo: z.string().describe('Repository name'),
- keyId: z.number().describe('Deploy key ID to delete'),
- });
- const RenderMarkdownSchema = z.object({
- text: z.string().describe('Markdown text to render'),
- mode: z.enum(['gfm', 'markdown']).optional().describe('Rendering mode: "gfm" for GitHub Flavored Markdown (default) or "markdown" for standard Markdown'),
- context: z.string().optional().describe('Repository context in the format "owner/repo" for repository-aware rendering (e.g., for issue references)'),
- });
- const RenderMarkdownRawSchema = z.object({
- text: z.string().describe('Raw markdown text to render to HTML'),
- });
- /**
- * Create and configure an MCP server with all tools and handlers
- */
- export function createMcpServer(gogsClient: GogsClient): Server {
- const server = new Server(
- {
- name: 'gogs-mcp-server',
- version: '1.0.0',
- },
- {
- capabilities: {
- tools: {},
- resources: {},
- },
- }
- );
- // Register tools
- server.setRequestHandler(ListToolsRequestSchema, async () => {
- return {
- tools: [
- {
- name: 'get_current_user',
- description: 'Get information about the authenticated user',
- inputSchema: {
- type: 'object',
- properties: {},
- },
- },
- {
- name: 'get_user',
- description: 'Get information about a specific user',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to get information for',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'search_users',
- description: 'Search for users by username',
- inputSchema: {
- type: 'object',
- properties: {
- query: {
- type: 'string',
- description: 'Search query for users',
- },
- limit: {
- type: 'number',
- description: 'Maximum number of results (default: 10)',
- },
- },
- required: ['query'],
- },
- },
- {
- name: 'list_user_repositories',
- description: 'List repositories for a user (or authenticated user if no username provided)',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username (omit for authenticated user)',
- },
- },
- },
- },
- {
- name: 'search_repositories',
- description: 'Search for repositories',
- inputSchema: {
- type: 'object',
- properties: {
- query: {
- type: 'string',
- description: 'Search query for repositories',
- },
- uid: {
- type: 'number',
- description: 'User ID to filter repositories',
- },
- limit: {
- type: 'number',
- description: 'Maximum number of results (default: 10)',
- },
- page: {
- type: 'number',
- description: 'Page number (default: 1)',
- },
- },
- required: ['query'],
- },
- },
- {
- name: 'get_repository',
- description: 'Get information about a specific repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'create_repository',
- description: 'Create a new repository for the authenticated user',
- inputSchema: {
- type: 'object',
- properties: {
- name: {
- type: 'string',
- description: 'Repository name',
- },
- description: {
- type: 'string',
- description: 'Repository description',
- },
- private: {
- type: 'boolean',
- description: 'Create as private repository (default: false)',
- },
- auto_init: {
- type: 'boolean',
- description: 'Initialize with README (default: false)',
- },
- gitignores: {
- type: 'string',
- description: 'Gitignore templates (e.g., "Go,VisualStudioCode")',
- },
- license: {
- type: 'string',
- description: 'License template (e.g., "MIT License")',
- },
- readme: {
- type: 'string',
- description: 'README template (default: "Default")',
- },
- },
- required: ['name'],
- },
- },
- {
- name: 'delete_repository',
- description: 'Delete a repository (requires admin access)',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_contents',
- description: 'Get file or directory contents from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- path: {
- type: 'string',
- description: 'File or directory path',
- },
- ref: {
- type: 'string',
- description: 'Branch, tag, or commit SHA (default: default branch)',
- },
- },
- required: ['owner', 'repo', 'path'],
- },
- },
- {
- name: 'get_raw_content',
- description: 'Get raw file content from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- ref: {
- type: 'string',
- description: 'Branch, tag, or commit SHA',
- },
- path: {
- type: 'string',
- description: 'File path',
- },
- },
- required: ['owner', 'repo', 'ref', 'path'],
- },
- },
- {
- name: 'list_branches',
- description: 'List all branches in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_commits',
- description: 'Get commit history from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- sha: {
- type: 'string',
- description: 'Branch name or commit SHA',
- },
- page: {
- type: 'number',
- description: 'Page number (default: 1)',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_tree',
- description: 'Get a git tree by SHA - provides low-level access to repository structure at a specific commit or tree SHA',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- sha: {
- type: 'string',
- description: 'Git tree SHA or commit SHA',
- },
- },
- required: ['owner', 'repo', 'sha'],
- },
- },
- {
- name: 'list_issues',
- description: 'List issues in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- state: {
- type: 'string',
- enum: ['open', 'closed', 'all'],
- description: 'Filter by state (default: open)',
- },
- labels: {
- type: 'string',
- description: 'Comma-separated list of label names',
- },
- page: {
- type: 'number',
- description: 'Page number (default: 1)',
- },
- per_page: {
- type: 'number',
- description: 'Results per page (default: 30)',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_issue',
- description: 'Get a specific issue by number',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- },
- required: ['owner', 'repo', 'number'],
- },
- },
- {
- name: 'create_issue',
- description: 'Create a new issue in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- title: {
- type: 'string',
- description: 'Issue title',
- },
- body: {
- type: 'string',
- description: 'Issue description',
- },
- assignee: {
- type: 'string',
- description: 'Username to assign the issue to',
- },
- milestone: {
- type: 'number',
- description: 'Milestone ID',
- },
- labels: {
- type: 'array',
- items: {
- type: 'number',
- },
- description: 'Array of label IDs',
- },
- },
- required: ['owner', 'repo', 'title'],
- },
- },
- {
- name: 'update_issue',
- description: 'Update an existing issue (including closing or reopening)',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- title: {
- type: 'string',
- description: 'Issue title',
- },
- body: {
- type: 'string',
- description: 'Issue description',
- },
- assignee: {
- type: 'string',
- description: 'Username to assign the issue to',
- },
- milestone: {
- type: 'number',
- description: 'Milestone ID',
- },
- state: {
- type: 'string',
- enum: ['open', 'closed'],
- description: 'Issue state',
- },
- labels: {
- type: 'array',
- items: {
- type: 'number',
- },
- description: 'Array of label IDs',
- },
- },
- required: ['owner', 'repo', 'number'],
- },
- },
- {
- name: 'list_issue_comments',
- description: 'List all comments on an issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- },
- required: ['owner', 'repo', 'number'],
- },
- },
- {
- name: 'create_issue_comment',
- description: 'Add a comment to an issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- body: {
- type: 'string',
- description: 'Comment text',
- },
- },
- required: ['owner', 'repo', 'number', 'body'],
- },
- },
- {
- name: 'update_issue_comment',
- description: 'Edit an existing comment on an issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- commentId: {
- type: 'number',
- description: 'Comment ID',
- },
- body: {
- type: 'string',
- description: 'Updated comment text',
- },
- },
- required: ['owner', 'repo', 'commentId', 'body'],
- },
- },
- {
- name: 'list_labels',
- description: 'List all labels in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_label',
- description: 'Get a specific label by ID',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- labelId: {
- type: 'number',
- description: 'Label ID',
- },
- },
- required: ['owner', 'repo', 'labelId'],
- },
- },
- {
- name: 'create_label',
- description: 'Create a new label in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- name: {
- type: 'string',
- description: 'Label name',
- },
- color: {
- type: 'string',
- description: '7-character hex color code with leading # (e.g., #ff0000)',
- },
- },
- required: ['owner', 'repo', 'name', 'color'],
- },
- },
- {
- name: 'update_label',
- description: 'Update an existing label',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- labelId: {
- type: 'number',
- description: 'Label ID',
- },
- name: {
- type: 'string',
- description: 'Label name',
- },
- color: {
- type: 'string',
- description: '7-character hex color code with leading # (e.g., #ff0000)',
- },
- },
- required: ['owner', 'repo', 'labelId'],
- },
- },
- {
- name: 'delete_label',
- description: 'Delete a label from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- labelId: {
- type: 'number',
- description: 'Label ID',
- },
- },
- required: ['owner', 'repo', 'labelId'],
- },
- },
- {
- name: 'list_issue_labels',
- description: 'List all labels on a specific issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- },
- required: ['owner', 'repo', 'number'],
- },
- },
- {
- name: 'add_issue_labels',
- description: 'Add labels to an issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- labels: {
- type: 'array',
- items: {
- type: 'number',
- },
- description: 'Array of label IDs to add',
- },
- },
- required: ['owner', 'repo', 'number', 'labels'],
- },
- },
- {
- name: 'remove_issue_label',
- description: 'Remove a specific label from an issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- labelId: {
- type: 'number',
- description: 'Label ID to remove',
- },
- },
- required: ['owner', 'repo', 'number', 'labelId'],
- },
- },
- {
- name: 'replace_issue_labels',
- description: 'Replace all labels on an issue with a new set',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- labels: {
- type: 'array',
- items: {
- type: 'number',
- },
- description: 'Array of label IDs to set (replaces all existing labels)',
- },
- },
- required: ['owner', 'repo', 'number', 'labels'],
- },
- },
- {
- name: 'remove_all_issue_labels',
- description: 'Remove all labels from an issue',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- number: {
- type: 'number',
- description: 'Issue number',
- },
- },
- required: ['owner', 'repo', 'number'],
- },
- },
- {
- name: 'list_milestones',
- description: 'List all milestones in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_milestone',
- description: 'Get a specific milestone by ID',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- milestoneId: {
- type: 'number',
- description: 'Milestone ID',
- },
- },
- required: ['owner', 'repo', 'milestoneId'],
- },
- },
- {
- name: 'create_milestone',
- description: 'Create a new milestone in a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- title: {
- type: 'string',
- description: 'Milestone title',
- },
- description: {
- type: 'string',
- description: 'Milestone description',
- },
- due_on: {
- type: 'string',
- description: 'Due date in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)',
- },
- },
- required: ['owner', 'repo', 'title'],
- },
- },
- {
- name: 'update_milestone',
- description: 'Update an existing milestone',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- milestoneId: {
- type: 'number',
- description: 'Milestone ID',
- },
- title: {
- type: 'string',
- description: 'Milestone title',
- },
- description: {
- type: 'string',
- description: 'Milestone description',
- },
- due_on: {
- type: 'string',
- description: 'Due date in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)',
- },
- state: {
- type: 'string',
- enum: ['open', 'closed'],
- description: 'Milestone state',
- },
- },
- required: ['owner', 'repo', 'milestoneId'],
- },
- },
- {
- name: 'delete_milestone',
- description: 'Delete a milestone from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- milestoneId: {
- type: 'number',
- description: 'Milestone ID',
- },
- },
- required: ['owner', 'repo', 'milestoneId'],
- },
- },
- {
- name: 'list_user_organizations',
- description: 'List organizations for the authenticated user',
- inputSchema: {
- type: 'object',
- properties: {},
- },
- },
- {
- name: 'create_organization',
- description: 'Create a new organization',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Organization username (alphanumeric, dashes, underscores)',
- },
- full_name: {
- type: 'string',
- description: 'Organization full name',
- },
- description: {
- type: 'string',
- description: 'Organization description',
- },
- website: {
- type: 'string',
- description: 'Organization website',
- },
- location: {
- type: 'string',
- description: 'Organization location',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'list_public_organizations',
- description: 'List public organizations for a specific user',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to get public organizations for',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'get_organization',
- description: 'Get information about a specific organization',
- inputSchema: {
- type: 'object',
- properties: {
- orgname: {
- type: 'string',
- description: 'Organization name',
- },
- },
- required: ['orgname'],
- },
- },
- {
- name: 'update_organization',
- description: 'Update an organization (requires owner permissions)',
- inputSchema: {
- type: 'object',
- properties: {
- orgname: {
- type: 'string',
- description: 'Organization name',
- },
- full_name: {
- type: 'string',
- description: 'Organization full name',
- },
- description: {
- type: 'string',
- description: 'Organization description',
- },
- website: {
- type: 'string',
- description: 'Organization website',
- },
- location: {
- type: 'string',
- description: 'Organization location',
- },
- },
- required: ['orgname'],
- },
- },
- {
- name: 'add_organization_member',
- description: 'Add or update organization membership (requires owner permissions)',
- inputSchema: {
- type: 'object',
- properties: {
- orgname: {
- type: 'string',
- description: 'Organization name',
- },
- username: {
- type: 'string',
- description: 'Username to add as member',
- },
- role: {
- type: 'string',
- enum: ['admin', 'member'],
- description: 'Member role (admin or member)',
- },
- },
- required: ['orgname', 'username', 'role'],
- },
- },
- {
- name: 'list_organization_teams',
- description: 'List teams in an organization',
- inputSchema: {
- type: 'object',
- properties: {
- orgname: {
- type: 'string',
- description: 'Organization name',
- },
- },
- required: ['orgname'],
- },
- },
- {
- name: 'create_team',
- description: 'Create a new team in an organization (requires admin permissions)',
- inputSchema: {
- type: 'object',
- properties: {
- orgname: {
- type: 'string',
- description: 'Organization name',
- },
- name: {
- type: 'string',
- description: 'Team name (max 30 characters, alphanumeric with dashes and dots)',
- },
- description: {
- type: 'string',
- description: 'Team description (max 255 characters)',
- },
- permission: {
- type: 'string',
- enum: ['read', 'write', 'admin'],
- description: 'Team permission level (default: read)',
- },
- },
- required: ['orgname', 'name'],
- },
- },
- {
- name: 'get_team',
- description: 'Get information about a specific team',
- inputSchema: {
- type: 'object',
- properties: {
- teamId: {
- type: 'number',
- description: 'Team ID',
- },
- },
- required: ['teamId'],
- },
- },
- {
- name: 'add_team_member',
- description: 'Add a user to a team (requires admin permissions)',
- inputSchema: {
- type: 'object',
- properties: {
- teamId: {
- type: 'number',
- description: 'Team ID',
- },
- username: {
- type: 'string',
- description: 'Username to add to the team',
- },
- },
- required: ['teamId', 'username'],
- },
- },
- {
- name: 'remove_team_member',
- description: 'Remove a user from a team (requires admin permissions)',
- inputSchema: {
- type: 'object',
- properties: {
- teamId: {
- type: 'number',
- description: 'Team ID',
- },
- username: {
- type: 'string',
- description: 'Username to remove from the team',
- },
- },
- required: ['teamId', 'username'],
- },
- },
- {
- name: 'list_releases',
- description: 'List all releases for a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'list_collaborators',
- description: 'List all collaborators for a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'check_collaborator',
- description: 'Check if a user is a collaborator on a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- username: {
- type: 'string',
- description: 'Username to check for collaborator status',
- },
- },
- required: ['owner', 'repo', 'username'],
- },
- },
- {
- name: 'add_collaborator',
- description: 'Add a collaborator to a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- username: {
- type: 'string',
- description: 'Username to add as collaborator',
- },
- permission: {
- type: 'string',
- enum: ['read', 'write', 'admin'],
- description: 'Permission level (default: write)',
- },
- },
- required: ['owner', 'repo', 'username'],
- },
- },
- {
- name: 'remove_collaborator',
- description: 'Remove a collaborator from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- username: {
- type: 'string',
- description: 'Username to remove as collaborator',
- },
- },
- required: ['owner', 'repo', 'username'],
- },
- },
- {
- name: 'list_user_emails',
- description: 'List email addresses for the authenticated user',
- inputSchema: {
- type: 'object',
- properties: {},
- },
- },
- {
- name: 'add_user_emails',
- description: 'Add email address(es) to the authenticated user account',
- inputSchema: {
- type: 'object',
- properties: {
- emails: {
- type: 'array',
- items: {
- type: 'string',
- },
- description: 'Array of email addresses to add',
- },
- },
- required: ['emails'],
- },
- },
- {
- name: 'delete_user_emails',
- description: 'Delete email address(es) from the authenticated user account',
- inputSchema: {
- type: 'object',
- properties: {
- emails: {
- type: 'array',
- items: {
- type: 'string',
- },
- description: 'Array of email addresses to delete',
- },
- },
- required: ['emails'],
- },
- },
- {
- name: 'list_user_keys',
- description: 'List public SSH keys for a specific user',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to list public keys for',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'list_my_keys',
- description: 'List public SSH keys for the authenticated user',
- inputSchema: {
- type: 'object',
- properties: {},
- },
- },
- {
- name: 'get_public_key',
- description: 'Get details of a specific public SSH key by ID',
- inputSchema: {
- type: 'object',
- properties: {
- keyId: {
- type: 'number',
- description: 'Public key ID',
- },
- },
- required: ['keyId'],
- },
- },
- {
- name: 'create_public_key',
- description: 'Create a new public SSH key for the authenticated user',
- inputSchema: {
- type: 'object',
- properties: {
- title: {
- type: 'string',
- description: 'Key title/name for identification',
- },
- key: {
- type: 'string',
- description: 'The public key content (SSH public key format)',
- },
- },
- required: ['title', 'key'],
- },
- },
- {
- name: 'delete_public_key',
- description: 'Delete a public SSH key by ID',
- inputSchema: {
- type: 'object',
- properties: {
- keyId: {
- type: 'number',
- description: 'Public key ID to delete',
- },
- },
- required: ['keyId'],
- },
- },
- {
- name: 'list_hooks',
- description: 'List all webhooks for a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'create_hook',
- description: 'Create a new webhook for a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- type: {
- type: 'string',
- enum: ['gogs', 'slack'],
- description: 'Webhook type (gogs or slack)',
- },
- config: {
- type: 'object',
- properties: {
- url: {
- type: 'string',
- description: 'URL to send webhook payloads to',
- },
- content_type: {
- type: 'string',
- enum: ['json', 'form'],
- description: 'Content type for payload (json or form)',
- },
- secret: {
- type: 'string',
- description: 'Optional secret for webhook validation',
- },
- channel: {
- type: 'string',
- description: 'Slack channel (for slack webhooks)',
- },
- username: {
- type: 'string',
- description: 'Slack username (for slack webhooks)',
- },
- icon_url: {
- type: 'string',
- description: 'Slack icon URL (for slack webhooks)',
- },
- color: {
- type: 'string',
- description: 'Slack color (for slack webhooks)',
- },
- },
- required: ['url', 'content_type'],
- description: 'Webhook configuration',
- },
- events: {
- type: 'array',
- items: {
- type: 'string',
- enum: ['create', 'delete', 'fork', 'push', 'issues', 'issue_comment', 'pull_request', 'release'],
- },
- description: 'Events that trigger the webhook (default: ["push"])',
- },
- active: {
- type: 'boolean',
- description: 'Whether the webhook is active (default: false)',
- },
- },
- required: ['owner', 'repo', 'type', 'config'],
- },
- },
- {
- name: 'update_hook',
- description: 'Update an existing webhook',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- hookId: {
- type: 'number',
- description: 'Webhook ID to update',
- },
- config: {
- type: 'object',
- properties: {
- url: {
- type: 'string',
- description: 'URL to send webhook payloads to',
- },
- content_type: {
- type: 'string',
- enum: ['json', 'form'],
- description: 'Content type for payload (json or form)',
- },
- secret: {
- type: 'string',
- description: 'Optional secret for webhook validation',
- },
- channel: {
- type: 'string',
- description: 'Slack channel (for slack webhooks)',
- },
- username: {
- type: 'string',
- description: 'Slack username (for slack webhooks)',
- },
- icon_url: {
- type: 'string',
- description: 'Slack icon URL (for slack webhooks)',
- },
- color: {
- type: 'string',
- description: 'Slack color (for slack webhooks)',
- },
- },
- required: ['url', 'content_type'],
- description: 'Webhook configuration',
- },
- events: {
- type: 'array',
- items: {
- type: 'string',
- enum: ['create', 'delete', 'fork', 'push', 'issues', 'issue_comment', 'pull_request', 'release'],
- },
- description: 'Events that trigger the webhook',
- },
- active: {
- type: 'boolean',
- description: 'Whether the webhook is active',
- },
- },
- required: ['owner', 'repo', 'hookId', 'config'],
- },
- },
- {
- name: 'delete_hook',
- description: 'Delete a webhook from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- hookId: {
- type: 'number',
- description: 'Webhook ID to delete',
- },
- },
- required: ['owner', 'repo', 'hookId'],
- },
- },
- {
- name: 'list_followers',
- description: 'List followers of a specific user',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to list followers for',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'list_following',
- description: 'List users that a specific user is following',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to list following for',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'check_following',
- description: 'Check if the authenticated user is following a target user',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to check if authenticated user is following',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'follow_user',
- description: 'Follow a user (authenticated user follows the target user)',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to follow',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'unfollow_user',
- description: 'Unfollow a user (authenticated user unfollows the target user)',
- inputSchema: {
- type: 'object',
- properties: {
- username: {
- type: 'string',
- description: 'Username to unfollow',
- },
- },
- required: ['username'],
- },
- },
- {
- name: 'list_deploy_keys',
- description: 'List all deploy keys for a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- },
- required: ['owner', 'repo'],
- },
- },
- {
- name: 'get_deploy_key',
- description: 'Get details of a specific deploy key',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- keyId: {
- type: 'number',
- description: 'Deploy key ID',
- },
- },
- required: ['owner', 'repo', 'keyId'],
- },
- },
- {
- name: 'create_deploy_key',
- description: 'Add a new deploy key to a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- title: {
- type: 'string',
- description: 'Deploy key title/name for identification',
- },
- key: {
- type: 'string',
- description: 'The public key content (SSH public key format)',
- },
- read_only: {
- type: 'boolean',
- description: 'Whether the key is read-only (default: true)',
- },
- },
- required: ['owner', 'repo', 'title', 'key'],
- },
- },
- {
- name: 'delete_deploy_key',
- description: 'Remove a deploy key from a repository',
- inputSchema: {
- type: 'object',
- properties: {
- owner: {
- type: 'string',
- description: 'Repository owner username',
- },
- repo: {
- type: 'string',
- description: 'Repository name',
- },
- keyId: {
- type: 'number',
- description: 'Deploy key ID to delete',
- },
- },
- required: ['owner', 'repo', 'keyId'],
- },
- },
- {
- name: 'render_markdown',
- description: 'Render markdown text to HTML with support for GitHub Flavored Markdown (GFM) and repository context',
- inputSchema: {
- type: 'object',
- properties: {
- text: {
- type: 'string',
- description: 'Markdown text to render',
- },
- mode: {
- type: 'string',
- enum: ['gfm', 'markdown'],
- description: 'Rendering mode: "gfm" for GitHub Flavored Markdown (default) or "markdown" for standard Markdown',
- },
- context: {
- type: 'string',
- description: 'Repository context in the format "owner/repo" for repository-aware rendering (e.g., for issue references)',
- },
- },
- required: ['text'],
- },
- },
- {
- name: 'render_markdown_raw',
- description: 'Render raw markdown text to HTML (simpler endpoint, plain text input)',
- inputSchema: {
- type: 'object',
- properties: {
- text: {
- type: 'string',
- description: 'Raw markdown text to render to HTML',
- },
- },
- required: ['text'],
- },
- },
- ],
- };
- });
- // Handle tool calls
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
- try {
- const { name, arguments: args } = request.params;
- switch (name) {
- case 'get_current_user': {
- const user = await gogsClient.getCurrentUser();
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(user, null, 2),
- },
- ],
- };
- }
- case 'get_user': {
- const { username } = GetUserSchema.parse(args);
- const user = await gogsClient.getUser(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(user, null, 2),
- },
- ],
- };
- }
- case 'search_users': {
- const { query, limit } = SearchUsersSchema.parse(args);
- const users = await gogsClient.searchUsers(query, limit);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(users, null, 2),
- },
- ],
- };
- }
- case 'list_user_repositories': {
- const { username } = ListUserReposSchema.parse(args);
- const repos = username
- ? await gogsClient.listUserRepositories(username)
- : await gogsClient.listMyRepositories();
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(repos, null, 2),
- },
- ],
- };
- }
- case 'search_repositories': {
- const { query, uid, limit, page } = SearchReposSchema.parse(args);
- const repos = await gogsClient.searchRepositories(query, { uid, limit, page });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(repos, null, 2),
- },
- ],
- };
- }
- case 'get_repository': {
- const { owner, repo } = GetRepoSchema.parse(args);
- const repository = await gogsClient.getRepository(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(repository, null, 2),
- },
- ],
- };
- }
- case 'create_repository': {
- const data = CreateRepoSchema.parse(args);
- const repo = await gogsClient.createRepository(data);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(repo, null, 2),
- },
- ],
- };
- }
- case 'delete_repository': {
- const { owner, repo } = DeleteRepoSchema.parse(args);
- await gogsClient.deleteRepository(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: `Repository ${owner}/${repo} deleted successfully`,
- },
- ],
- };
- }
- case 'get_contents': {
- const { owner, repo, path, ref } = GetContentsSchema.parse(args);
- const contents = await gogsClient.getContents(owner, repo, path, ref);
- // If it's a file with base64 content, decode it
- if (!Array.isArray(contents) && contents.type === 'file' && contents.content) {
- const decodedContent = Buffer.from(contents.content, 'base64').toString('utf-8');
- return {
- content: [
- {
- type: 'text',
- text: `File: ${contents.path}\nSize: ${contents.size} bytes\nSHA: ${contents.sha}\n\nContent:\n${decodedContent}`,
- },
- ],
- };
- }
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(contents, null, 2),
- },
- ],
- };
- }
- case 'get_raw_content': {
- const { owner, repo, ref, path } = GetRawContentSchema.parse(args);
- const content = await gogsClient.getRawContent(owner, repo, ref, path);
- return {
- content: [
- {
- type: 'text',
- text: content,
- },
- ],
- };
- }
- case 'list_branches': {
- const { owner, repo } = ListBranchesSchema.parse(args);
- const branches = await gogsClient.listBranches(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(branches, null, 2),
- },
- ],
- };
- }
- case 'get_commits': {
- const { owner, repo, sha, page } = GetCommitsSchema.parse(args);
- const commits = await gogsClient.getCommits(owner, repo, { sha, page });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(commits, null, 2),
- },
- ],
- };
- }
- case 'get_tree': {
- const { owner, repo, sha } = GetTreeSchema.parse(args);
- const tree = await gogsClient.getTree(owner, repo, sha);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(tree, null, 2),
- },
- ],
- };
- }
- case 'list_issues': {
- const { owner, repo, state, labels, page, per_page } = ListIssuesSchema.parse(args);
- const issues = await gogsClient.listIssues(owner, repo, { state, labels, page, per_page });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(issues, null, 2),
- },
- ],
- };
- }
- case 'get_issue': {
- const { owner, repo, number } = GetIssueSchema.parse(args);
- const issue = await gogsClient.getIssue(owner, repo, number);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(issue, null, 2),
- },
- ],
- };
- }
- case 'create_issue': {
- const { owner, repo, title, body, assignee, milestone, labels } = CreateIssueSchema.parse(args);
- const issue = await gogsClient.createIssue(owner, repo, {
- title,
- body,
- assignee,
- milestone,
- labels,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(issue, null, 2),
- },
- ],
- };
- }
- case 'update_issue': {
- const { owner, repo, number, title, body, assignee, milestone, state, labels } = UpdateIssueSchema.parse(args);
- const issue = await gogsClient.updateIssue(owner, repo, number, {
- title,
- body,
- assignee,
- milestone,
- state,
- labels,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(issue, null, 2),
- },
- ],
- };
- }
- case 'list_issue_comments': {
- const { owner, repo, number } = ListIssueCommentsSchema.parse(args);
- const comments = await gogsClient.listIssueComments(owner, repo, number);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(comments, null, 2),
- },
- ],
- };
- }
- case 'create_issue_comment': {
- const { owner, repo, number, body } = CreateIssueCommentSchema.parse(args);
- const comment = await gogsClient.createIssueComment(owner, repo, number, body);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(comment, null, 2),
- },
- ],
- };
- }
- case 'update_issue_comment': {
- const { owner, repo, commentId, body } = UpdateIssueCommentSchema.parse(args);
- const comment = await gogsClient.updateIssueComment(owner, repo, commentId, body);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(comment, null, 2),
- },
- ],
- };
- }
- case 'list_labels': {
- const { owner, repo } = ListLabelsSchema.parse(args);
- const labels = await gogsClient.listLabels(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(labels, null, 2),
- },
- ],
- };
- }
- case 'get_label': {
- const { owner, repo, labelId } = GetLabelSchema.parse(args);
- const label = await gogsClient.getLabel(owner, repo, labelId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(label, null, 2),
- },
- ],
- };
- }
- case 'create_label': {
- const { owner, repo, name, color } = CreateLabelSchema.parse(args);
- const label = await gogsClient.createLabel(owner, repo, { name, color });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(label, null, 2),
- },
- ],
- };
- }
- case 'update_label': {
- const { owner, repo, labelId, name, color } = UpdateLabelSchema.parse(args);
- const label = await gogsClient.updateLabel(owner, repo, labelId, { name, color });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(label, null, 2),
- },
- ],
- };
- }
- case 'delete_label': {
- const { owner, repo, labelId } = DeleteLabelSchema.parse(args);
- await gogsClient.deleteLabel(owner, repo, labelId);
- return {
- content: [
- {
- type: 'text',
- text: `Label ${labelId} deleted successfully from ${owner}/${repo}`,
- },
- ],
- };
- }
- case 'list_issue_labels': {
- const { owner, repo, number } = ListIssueLabelsSchema.parse(args);
- const labels = await gogsClient.listIssueLabels(owner, repo, number);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(labels, null, 2),
- },
- ],
- };
- }
- case 'add_issue_labels': {
- const { owner, repo, number, labels } = AddIssueLabelsSchema.parse(args);
- const result = await gogsClient.addIssueLabels(owner, repo, number, labels);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(result, null, 2),
- },
- ],
- };
- }
- case 'remove_issue_label': {
- const { owner, repo, number, labelId } = RemoveIssueLabelSchema.parse(args);
- await gogsClient.removeIssueLabel(owner, repo, number, labelId);
- return {
- content: [
- {
- type: 'text',
- text: `Label ${labelId} removed successfully from issue #${number}`,
- },
- ],
- };
- }
- case 'replace_issue_labels': {
- const { owner, repo, number, labels } = ReplaceIssueLabelsSchema.parse(args);
- const result = await gogsClient.replaceIssueLabels(owner, repo, number, labels);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(result, null, 2),
- },
- ],
- };
- }
- case 'remove_all_issue_labels': {
- const { owner, repo, number } = RemoveAllIssueLabelsSchema.parse(args);
- await gogsClient.removeAllIssueLabels(owner, repo, number);
- return {
- content: [
- {
- type: 'text',
- text: `All labels removed successfully from issue #${number}`,
- },
- ],
- };
- }
- case 'list_milestones': {
- const { owner, repo } = ListMilestonesSchema.parse(args);
- const milestones = await gogsClient.listMilestones(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(milestones, null, 2),
- },
- ],
- };
- }
- case 'get_milestone': {
- const { owner, repo, milestoneId } = GetMilestoneSchema.parse(args);
- const milestone = await gogsClient.getMilestone(owner, repo, milestoneId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(milestone, null, 2),
- },
- ],
- };
- }
- case 'create_milestone': {
- const { owner, repo, title, description, due_on } = CreateMilestoneSchema.parse(args);
- const milestone = await gogsClient.createMilestone(owner, repo, {
- title,
- description,
- due_on,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(milestone, null, 2),
- },
- ],
- };
- }
- case 'update_milestone': {
- const { owner, repo, milestoneId, title, description, due_on, state } = UpdateMilestoneSchema.parse(args);
- const milestone = await gogsClient.updateMilestone(owner, repo, milestoneId, {
- title,
- description,
- due_on,
- state,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(milestone, null, 2),
- },
- ],
- };
- }
- case 'delete_milestone': {
- const { owner, repo, milestoneId } = DeleteMilestoneSchema.parse(args);
- await gogsClient.deleteMilestone(owner, repo, milestoneId);
- return {
- content: [
- {
- type: 'text',
- text: `Milestone ${milestoneId} deleted successfully from ${owner}/${repo}`,
- },
- ],
- };
- }
- case 'list_user_organizations': {
- const organizations = await gogsClient.listUserOrganizations();
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(organizations, null, 2),
- },
- ],
- };
- }
- case 'create_organization': {
- const { username, full_name, description, website, location } = CreateOrganizationSchema.parse(args);
- const organization = await gogsClient.createOrganization({
- username,
- full_name,
- description,
- website,
- location,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(organization, null, 2),
- },
- ],
- };
- }
- case 'list_public_organizations': {
- const { username } = ListPublicOrganizationsSchema.parse(args);
- const organizations = await gogsClient.listPublicOrganizations(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(organizations, null, 2),
- },
- ],
- };
- }
- case 'get_organization': {
- const { orgname } = GetOrganizationSchema.parse(args);
- const organization = await gogsClient.getOrganization(orgname);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(organization, null, 2),
- },
- ],
- };
- }
- case 'update_organization': {
- const { orgname, full_name, description, website, location } = UpdateOrganizationSchema.parse(args);
- const organization = await gogsClient.updateOrganization(orgname, {
- full_name,
- description,
- website,
- location,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(organization, null, 2),
- },
- ],
- };
- }
- case 'add_organization_member': {
- const { orgname, username, role } = AddOrganizationMemberSchema.parse(args);
- await gogsClient.addOrganizationMember(orgname, username, role);
- return {
- content: [
- {
- type: 'text',
- text: `User ${username} added to organization ${orgname} with role ${role}`,
- },
- ],
- };
- }
- case 'list_organization_teams': {
- const { orgname } = ListOrganizationTeamsSchema.parse(args);
- const teams = await gogsClient.listOrganizationTeams(orgname);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(teams, null, 2),
- },
- ],
- };
- }
- case 'create_team': {
- const { orgname, name, description, permission } = CreateTeamSchema.parse(args);
- const team = await gogsClient.createTeam(orgname, {
- name,
- description,
- permission,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(team, null, 2),
- },
- ],
- };
- }
- case 'get_team': {
- const { teamId } = GetTeamSchema.parse(args);
- const team = await gogsClient.getTeam(teamId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(team, null, 2),
- },
- ],
- };
- }
- case 'add_team_member': {
- const { teamId, username } = AddTeamMemberSchema.parse(args);
- await gogsClient.addTeamMember(teamId, username);
- return {
- content: [
- {
- type: 'text',
- text: `User ${username} added to team ${teamId} successfully`,
- },
- ],
- };
- }
- case 'remove_team_member': {
- const { teamId, username } = RemoveTeamMemberSchema.parse(args);
- await gogsClient.removeTeamMember(teamId, username);
- return {
- content: [
- {
- type: 'text',
- text: `User ${username} removed from team ${teamId} successfully`,
- },
- ],
- };
- }
- case 'list_releases': {
- const { owner, repo } = ListReleasesSchema.parse(args);
- const releases = await gogsClient.listReleases(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(releases, null, 2),
- },
- ],
- };
- }
- case 'list_collaborators': {
- const { owner, repo } = ListCollaboratorsSchema.parse(args);
- const collaborators = await gogsClient.listCollaborators(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(collaborators, null, 2),
- },
- ],
- };
- }
- case 'check_collaborator': {
- const { owner, repo, username } = CheckCollaboratorSchema.parse(args);
- const isCollaborator = await gogsClient.checkCollaborator(owner, repo, username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({ isCollaborator, username, repository: `${owner}/${repo}` }, null, 2),
- },
- ],
- };
- }
- case 'add_collaborator': {
- const { owner, repo, username, permission } = AddCollaboratorSchema.parse(args);
- await gogsClient.addCollaborator(owner, repo, username, permission);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully added ${username} as collaborator to ${owner}/${repo}`,
- permission: permission || 'write'
- }, null, 2),
- },
- ],
- };
- }
- case 'remove_collaborator': {
- const { owner, repo, username } = RemoveCollaboratorSchema.parse(args);
- await gogsClient.removeCollaborator(owner, repo, username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully removed ${username} as collaborator from ${owner}/${repo}`
- }, null, 2),
- },
- ],
- };
- }
- case 'list_user_emails': {
- const emails = await gogsClient.listUserEmails();
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(emails, null, 2),
- },
- ],
- };
- }
- case 'add_user_emails': {
- const { emails } = AddUserEmailsSchema.parse(args);
- const addedEmails = await gogsClient.addUserEmails(emails);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(addedEmails, null, 2),
- },
- ],
- };
- }
- case 'delete_user_emails': {
- const { emails } = DeleteUserEmailsSchema.parse(args);
- await gogsClient.deleteUserEmails(emails);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully deleted ${emails.length} email address(es)`,
- emails
- }, null, 2),
- },
- ],
- };
- }
- case 'list_user_keys': {
- const { username } = ListUserKeysSchema.parse(args);
- const keys = await gogsClient.listUserKeys(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(keys, null, 2),
- },
- ],
- };
- }
- case 'list_my_keys': {
- const keys = await gogsClient.listMyKeys();
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(keys, null, 2),
- },
- ],
- };
- }
- case 'get_public_key': {
- const { keyId } = GetPublicKeySchema.parse(args);
- const key = await gogsClient.getPublicKey(keyId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(key, null, 2),
- },
- ],
- };
- }
- case 'create_public_key': {
- const { title, key } = CreatePublicKeySchema.parse(args);
- const newKey = await gogsClient.createPublicKey({ title, key });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(newKey, null, 2),
- },
- ],
- };
- }
- case 'delete_public_key': {
- const { keyId } = DeletePublicKeySchema.parse(args);
- await gogsClient.deletePublicKey(keyId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully deleted public key with ID ${keyId}`,
- keyId
- }, null, 2),
- },
- ],
- };
- }
- case 'list_hooks': {
- const { owner, repo } = ListHooksSchema.parse(args);
- const hooks = await gogsClient.listHooks(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(hooks, null, 2),
- },
- ],
- };
- }
- case 'create_hook': {
- const { owner, repo, type, config, events, active } = CreateHookSchema.parse(args);
- const hook = await gogsClient.createHook(owner, repo, {
- type,
- config,
- events,
- active,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(hook, null, 2),
- },
- ],
- };
- }
- case 'update_hook': {
- const { owner, repo, hookId, config, events, active } = UpdateHookSchema.parse(args);
- const hook = await gogsClient.updateHook(owner, repo, hookId, {
- config,
- events,
- active,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(hook, null, 2),
- },
- ],
- };
- }
- case 'delete_hook': {
- const { owner, repo, hookId } = DeleteHookSchema.parse(args);
- await gogsClient.deleteHook(owner, repo, hookId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully deleted webhook ${hookId} from ${owner}/${repo}`,
- hookId,
- repository: `${owner}/${repo}`
- }, null, 2),
- },
- ],
- };
- }
- case 'list_followers': {
- const { username } = ListFollowersSchema.parse(args);
- const followers = await gogsClient.listFollowers(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(followers, null, 2),
- },
- ],
- };
- }
- case 'list_following': {
- const { username } = ListFollowingSchema.parse(args);
- const following = await gogsClient.listFollowing(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(following, null, 2),
- },
- ],
- };
- }
- case 'check_following': {
- const { username } = CheckFollowingSchema.parse(args);
- const isFollowing = await gogsClient.checkFollowing(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- isFollowing,
- username,
- message: isFollowing
- ? `You are following ${username}`
- : `You are not following ${username}`
- }, null, 2),
- },
- ],
- };
- }
- case 'follow_user': {
- const { username } = FollowUserSchema.parse(args);
- await gogsClient.followUser(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully followed user ${username}`,
- username
- }, null, 2),
- },
- ],
- };
- }
- case 'unfollow_user': {
- const { username } = UnfollowUserSchema.parse(args);
- await gogsClient.unfollowUser(username);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully unfollowed user ${username}`,
- username
- }, null, 2),
- },
- ],
- };
- }
- case 'list_deploy_keys': {
- const { owner, repo } = ListDeployKeysSchema.parse(args);
- const keys = await gogsClient.listDeployKeys(owner, repo);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(keys, null, 2),
- },
- ],
- };
- }
- case 'get_deploy_key': {
- const { owner, repo, keyId } = GetDeployKeySchema.parse(args);
- const key = await gogsClient.getDeployKey(owner, repo, keyId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify(key, null, 2),
- },
- ],
- };
- }
- case 'create_deploy_key': {
- const { owner, repo, title, key, read_only } = CreateDeployKeySchema.parse(args);
- const deployKey = await gogsClient.createDeployKey(owner, repo, {
- title,
- key,
- read_only,
- });
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: 'Deploy key created successfully',
- key: deployKey
- }, null, 2),
- },
- ],
- };
- }
- case 'delete_deploy_key': {
- const { owner, repo, keyId } = DeleteDeployKeySchema.parse(args);
- await gogsClient.deleteDeployKey(owner, repo, keyId);
- return {
- content: [
- {
- type: 'text',
- text: JSON.stringify({
- success: true,
- message: `Successfully deleted deploy key ${keyId}`,
- keyId
- }, null, 2),
- },
- ],
- };
- }
- case 'render_markdown': {
- const { text, mode, context } = RenderMarkdownSchema.parse(args);
- const html = await gogsClient.renderMarkdown({
- text,
- mode,
- context,
- });
- return {
- content: [
- {
- type: 'text',
- text: html,
- },
- ],
- };
- }
- case 'render_markdown_raw': {
- const { text } = RenderMarkdownRawSchema.parse(args);
- const html = await gogsClient.renderMarkdownRaw(text);
- return {
- content: [
- {
- type: 'text',
- text: html,
- },
- ],
- };
- }
- default:
- throw new Error(`Unknown tool: ${name}`);
- }
- } catch (error) {
- if (error instanceof Error) {
- return {
- content: [
- {
- type: 'text',
- text: `Error: ${error.message}`,
- },
- ],
- isError: true,
- };
- }
- throw error;
- }
- });
- // Handle resources (optional - for browsing repository structure)
- server.setRequestHandler(ListResourcesRequestSchema, async () => {
- return {
- resources: [],
- };
- });
- server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
- throw new Error('Resource reading not yet implemented');
- });
- return server;
- }
|