GitLab MCP Server

José M. Requena Plens·jmrplens.gitlab-mcp-server

GitLab MCP server exposing the REST v4 and GraphQL APIs as tools for AI assistants.

A Model Context Protocol (MCP) server that connects AI assistants (Claude, Cursor, VS Code + Copilot, and any MCP client) to GitLab.com or self-managed GitLab instances. Covers the full REST API v4 and GraphQL with automatic edition gating, roughly 850 to 1080 tools depending on the GitLab tier, plus 45 MCP resources, 37 prompts, argument completions, progress notifications and resource subscriptions. Single static binary, stdio and HTTP transports, read-only and safe (mutation-preview) modes, and per-client configuration examples in the documentation.

winget install --id jmrplens.gitlab-mcp-server --exact --source winget

Latest 3.0.0·September 10, 2026

Release Notes

Changelog

✨ Features

• b771c0541b03d42adaa09dc83ff3c350a8bf9631:feat!: remove what v2 deprecated, minus the one window that never opened (#641) (@jmrplens) • e9626dfda03695a6e367a8450f94eab3c9f7a858:feat(achievements): take the avatar upload, and judge the GraphQL documents that carry a file (#592) (@jmrplens) • 0664a2861ec3beff7f07f369735f43c6debbb86d:feat(apiexposes): pin the condition GitLab sends each REST entity field under (#622) (@jmrplens) • 73b04d36a9d15593c403764d14c742420708f3de:feat(audit): add R-PATH, the dimension that reads the request rather than the surface (#598) (@jmrplens) • bf04b7714cf6cf2f2830133e02ccd480c77f964f:feat(audit): ask a booted GitLab what its own REST API is (#650) (@jmrplens) • d6993c06e5ec0fe37ad6a03dcee76846fc734cb8:feat(audit): ask the sent question of GraphQL, where nothing asked it (#648) (@jmrplens) • 0b23a9e474b0e7dc2f3921c0247b75213a0aad94:feat(audit): check the prose a meta-tool serves against the parameters it takes (#590) (@jmrplens) • f8f8f9c51504d49abff33a2b0c3df8276031ecbf:feat(audit): judge every GraphQL decoder against the document it decodes (#621) (@jmrplens) • ca4d86a2755d01a2d62ace3c825961e9a7c444e6:feat(audit): pin what GitLab says its own API returns, from the document GitLab generates (#599) (@jmrplens) • de07060d299752e5cf3e3bc4642699f5252e3ffa:feat(audit): read the SDK's enum values instead of trusting the field (#527) (@jmrplens) • be21f5e7098ca6a23305036f37dbf81e6e1fe4d6:feat(audit): report the output fields GitLab's own document says it does not send (#585) (@jmrplens) • b62edb0e066e8dda9f81fb9eddab800f2669d589:feat(audit): say which sent findings belong upstream in client-go (#654) (@jmrplens) • b244e4149b961f84203beb2271b335caad4088b0:feat(audit_1to1): ask the shape check at type grain, and adjudicate what it found (#589) (@jmrplens) • cb452bd5b31f367425a161a795c1ad60f059ec83:feat(bench): measure and publish what the server costs to run (#463) (@jmrplens) • 80245f6d4b89d86249165c16ebd6a8d574b3b961:feat(bench): measure whether a bound leaves the quiet tenant better off (#597) (@jmrplens) • 5492f2b51f6434e5a388d580f7b831cdb2672661:feat(bench): step one process up to a thousand credentials, with a profile at every step (#534) (@jmrplens) • b2c4bdd523f8288e55fe98f47a7905aba23509d3:feat(catalog): declare the documented value sets as schema enums (#494) (@jmrplens) • 13371b538326547143fe0387a18f5198d274fd8b:feat(catalog): embed the canonical resource of every get action again (#503) (@jmrplens) • 735329de6c55074ec76cb7778168d74ff283b6ac:feat(config): prefix every server variable with GITLAB_MCP_, the GITLAB_ switches included (#523) (@jmrplens) • 124f103b09e83cc9286947b2cb330233697ef03c:feat(dependencyfirewall): expose the Dependency Firewall evaluate endpoint (#451) (@jmrplens) • 36089b8d750f2898bec3894bdd802eae2ff32b84:feat(epics): expose what the Work Items API offers an epic, and publish only what GitLab sends (#593) (@jmrplens) • 764a12fd016410772465a6e45b35d8d89df0fbe5:feat(gen_testing_docs): pass -timeout through, refresh testing.md, gate it in CI (#441) (@jmrplens) • 1c5edb74470a17a98af4776c056b478521625859:feat(geo): publish what a Geo site and its status send, declare the matrix (#665) (@jmrplens) • 6befc450256254b2d1b10727d4762b68bc6c905b:feat(gitlab): read a field client-go does not model from the captured response (#625) (@jmrplens) • 677e1dbf53eaa0e1638da772690d534857e56b5f:feat(graphql): judge every document against the schema an instance serves today (#579) (@jmrplens) • 476f7ad74a057e6c78062c91492a5a89c5456d24:feat(graphql): make the mocks refuse what GitLab refuses, and fix the nine tools that proved (#575) (@jmrplens) • 04e528414424db9835931491f40047fcfc2fc90b:feat(http): believe the client-address header only from listed proxies (#480) (@jmrplens) • 97132dc33328e162b0fb7a6d75e7c07bf389bfd1:feat(http): meter tools/list on a bucket of its own (#566) (@jmrplens) • e5402d301beda45e8150d7ccdc2b866350d773f6:feat(http): report draining on /health and fingerprint the served configuration (#487) (@jmrplens) • f34c38a51be98c1938b9ed7f9d559131fe7071d6:feat(members): read what client-go's member structs do not carry off the captured response (#628) (@jmrplens) • 57bfc35f12cff2ed7e67395ecd92e19b0e65e5ef:feat(mergerequests): publish 15 fields and declare 34 the server never asks for (#668) (@jmrplens) • 6a334cc98778a20b0e3a7cf2895e1b27305ae0b9:feat(notes): read what client-go does not model off the captured response, and publish only what GitLab sends (#626) (@jmrplens) • 397c61ad4723f7f8a5941acb490a15c560f68580:feat(npm): install via npx with a per-platform binary wrapper (#323) (@jmrplens) • 22e7650e69f8ff950361ffaec30383ed248dc456:feat(release): harden the whole release chain for a definitive 2.7.6 (#326) (@jmrplens) • 11a3a2edd5d2f06641d1fbb9607dbc047e93327b:feat(release): ship the server on NuGet as a .NET tool (#526) (@jmrplens) • 87e8f3e689efa8a7218029baae6098722e250993:feat(security)!: confirm push-mirror creation and filter the catalog by token scope (#673) (@jmrplens) • 67f63e5451e6e02039c2a3ba5f2244c4bfd027af:feat(security)!: refuse outbound destinations the operator did not choose (#676) (@jmrplens) • 072ea7a3ef02738bb72c364a06c4b3302965e75a:feat(server): probe the listener the server actually has, as the image's health check (#481) (@jmrplens) • ab686b91e6012704a6fd58be7b247e5770b08aa8:feat(serverpool): say which eviction happened, and bound watchers across the process (#577) (@jmrplens) • 87334adc5a01331d3122b5ddfb402b48782d1790:feat(stdio): serve a read_api token the read-only surface, as HTTP does (#505) (@jmrplens) • 81b6aacbc06074407ecdba6354a6b3f55549dc52:feat(surface): read the six response fields client-go declares no member for (#629) (@jmrplens) • 7733804423c0229c27b667f862160c34688da811:feat(tokens): read the granular, impersonation and resource fields no token struct carries (#630) (@jmrplens) • 679a1bd33d826496bc848e80cfef7dde49aa5a8d:feat(tooling): gate the Markdown escaping rule, and fix everything it found (#594) (@jmrplens) • fcf3469591492da9c17c79a5ec5d797445953f3e:feat(tools): publish 15 member-family fields and declare 9 GitLab never sends (#664) (@jmrplens) • b8f700151a32f3b8e50103ed679b58af02a9b002:feat(tools): publish 36 fields GitLab sends across six packages (#661) (@jmrplens) • 04d222546becbc41d524f7709a73fbdef183f5cb:feat(tools): publish the tail of the fields GitLab sends and we dropped (#656) (@jmrplens) • 03a11e3e38cbfd8147871182f954c650c618ec58:feat(users): publish 45 fields and declare 19 the route set cannot send (#670) (@jmrplens) • bc47d37cadc246b983ed999edcaf085fb2f3633f:feat(workitems): expose every filter and widget client-go carries, and the objects behind them (#591) (@jmrplens) • cd541e9176553ea36bd27e6e067983d23eddf29d:feat: update client-go to v2.64.0 and expose the achievements service it brought (#560) (@jmrplens)

🐛 Bug Fixes

• a3dcafcccd1a774223503e33892b0e72dba222d5:fix(audit): compare against an SDK struct that tags nothing, instead of reporting all of it as ours (#582) (@jmrplens) • 0adc6f0a7de2cfcfe3646c548ba70c405226f83c:fix(audit): judge a type named as a field when a converter pairs it (#646) (@jmrplens) • c4f60bb403f666933aa467621d28683fb6fea86f:fix(audit): read a merged Grape exposure as the keys it contributes (#655) (@jmrplens) • 8c1df8cf8f5ddb2ff79014464f7af5abd13b3ae7:fix(audit_1to1): read a reopened Ruby class, promote embeds, nest through any struct, annotate per field (#623) (@jmrplens) • f22a164991a14535c25977851669b12cf08f7b09:fix(bench): measure what a credential costs to hold, not only to serve (#544) (@jmrplens) • 041bd0272541d3a44fb8c3a90b8afaa2ff03694b:fix(config): say 3.1.0, not v3, as the release that drops the old variable names (#680) (@jmrplens) • 4f512cb61e0530d77aa4ef227dc4cc71a7c7f720:fix(e2e): build the dynamic catalog the way the server does, and read a preview as the error it is (#475) (@jmrplens) • febc9600aeee3cf8379f70a9f8ac2e5bf7f62ee6:fix(epicissues): move the child under its parent the way GitLab accepts (#606) (@jmrplens) • 9ec10204cb456096bf71f700dbb743dd2aa890ee:fix(eval): give the thirteen colliding evaluator cases their own identifiers (#433) (@jmrplens) • 9c5cc8d56146c5eb4286829cd77a2a861a357237:fix(http): conform to the authorization and transport specifications, and refresh dependency pins (#328) (@jmrplens) • 867be652e3d7b20074d7c4a2abd8446210a84c4f:fix(http): make the OAuth surface honest, and admit read-only credentials (#324) (@jmrplens) • a64cc4437e8b502e109d3b70f59b09c2a978be7f:fix(http): refuse the free-instance hatch on a listener anyone can reach (#645) (@jmrplens) • 0f08072df9270d76955318b4a37d9f3f76af115b:fix(markdown): size every hand-written code fence to its body, and gate the class (#677) (@jmrplens) • 8d4e520751ad8908e2114d86af358cedaa88a171:fix(mcp): a tool call could kill the server, and subscriptions were dead by default (#334) (@jmrplens) • acb3b16d98939f6f7077544f0f59f71e972bb6dc:fix(mcp): conform to the server-surface specifications (#333) (@jmrplens) • 76c6aa1db4645df02f7496c868519df02d18abca:fix(mrapprovals): publish the four fields GitLab answers with, not the deprecated POST's twenty-four (#586) (@jmrplens) • d4b0fdbc89090d18444fa5e69ae63a6d7aa0f1d9:fix(oauth): conform to the three authorization sub-pages, and keep the raw token out of the identity cache (#532) (@jmrplens) • dc19efbeda4b24f0e412ebe45413477d89477c4c:fix(oauth): refuse unverified TLS, and stop calling an unadmitted token invalid (#331) (@jmrplens) • 07b9e8693dba602e8858981370e6256acb8c7b4e:fix(oauth): serve the protected-resource document only on its derived path (#456) (@jmrplens) • 32b25451e4b22ff17dcfa86be537acc58bbdf928:fix(pagination): page backwards where GitLab allows it, and stop advertising it where it does not (#595) (@jmrplens) • 52841e96648e731309c7ce6cf6280c35d7abde71:fix(projects): answer a project with no push rules instead of dereferencing nil (#605) (@j

Installer type: portable

x64—61C512E7E6EB386660DBD546AD47A54C2FA2441040C1D7BBCFAFF605EE548E98
arm64—4B9FC194A780ACBF93D2839CE2D9E82C318F1A81D712C0B359B1E440A9B09CFA

Details

Homepage
https://github.com/jmrplens/gitlab-mcp-server
License
MIT
Publisher
José M. Requena Plens
Support
https://github.com/jmrplens/gitlab-mcp-server/issues
Privacy Policy
https://github.com/jmrplens/gitlab-mcp-server/blob/main/PRIVACY.md
Moniker
gitlab-mcp-server

Tags

aici-cdclaudedevopsgitlabgraphqlllmmcpmodel-context-protocolrest-api

Older versions (13)

2.7.5
x64—0E8B5E5AC1343CB68AC565A56538654EE59541A827BB3F20A25C04AD525B4814
arm64—7EB27DD48CC55911D8E30CC4D633157AE850B1805496EE73648232A645547C2A
2.7.4
x64—7097CDE23FEEA6C81961EB71CA7FD957522A61AF5116006BCBC277FD8A7DC8EB
arm64—06633810A809C7144680F3D8FBA9F2598383E42A8091F05D2D9C91D8F5A43E08
2.7.3
x64—07734C2578924CE407CCB72996CBE58534A106C2427FDE08E049E86AEB964AE8
arm64—2CC6BE9F5C8E429C1181BC5931E4E2C2D7F62EE3D5A4E8E24BE082E9659F7BF5
2.7.1
x64—75FE9602437DF6CA7F029D1ABBF33F6035E3E9FA806748AFFE7CF835F2410C62
arm64—C753537E2420AD164E6C1D3A6D601D72BE431D7964C63DE8E2BE51D678EA7286
2.7.0
x64—6F1715E8EA5B3E96A5896F5A8A340242704218B777711C8E42DC7797ACAD6B28
arm64—4A03D2B91824FAF07519CC97243B7371AADB994E036FF4EE2BBF8518BB8DE425
2.6.6
x64—444B6ED7C159BC4CC6AF0007F1A96C4BF254BBBF5CCCCE4E56421FBCC6F447D7
arm64—AF74ACC8164A8D60834A323E3A7F2870063FCDFD51D2E237F8A330E312BB01BE
2.6.5
x64—8FCB712A93C04948F87C6CBFC73F1BE70117CC38D34B18E4866B4C27DBD60989
arm64—FEF73AC3532CEE3A6D2DE6F0409620DDBC480BD79F2A404F5A794FCB62FDFB5D
2.6.4
x64—339B0EC72A4AB48FAF0899757846345BCFDD695610BEA6D9CFEC5D886F7B808B
arm64—8D1DE3C10631113F555E6F6AF81775D0D235A364704B228C420AFD2D528F57EA
2.6.1
x64—C45CE18FF81ECD7D71AFF1B63CDF27FBA9628EEBEB9D31E74B257F470A1C4025
arm64—6651FCADFCAC14681FD360B930D6FD06C53157EE810A59C81D9867517632B095
2.6.0
x64—95E04E5CCCE5A8577164275AB0FA08C97FB402CFB18939A69B8A824917F1A9D7
arm64—75CEF96419383DE22DC6FA8534DA220E96334F0F20E4562C58B5D062A59F8C0A
2.5.3
x64—0B05DD3DB77380039EDB10D02F6A7F890E656EB2EF2897F1473DD1477BC3DDF3
arm64—CE028B412ACEFD29A7BB340B1130DB099CBE7531A98C5153CF402D9CB1E3E8C6
2.5.2
x64—64795B71C4749F40CAA513DC1D040CFF97119C55592FBF4C12AA484050D808AF
arm64—301A75FADDE1D63EF2837E97FB769C51EA31B3EE0BC94D0A5FC52E2A533C0832
2.5.0
x64—F802F8197535782F1A7357F5DF42117766ADCFF29EC94973D3E9B70389ECB042
arm64—6DA31DA26F9BD95A42B0AFA2C214903342447794A1226F5F77133A18C8FB12A2