gitlab-api 25.15.27__tar.gz → 25.15.30__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitlab_api-25.15.27/gitlab_api.egg-info → gitlab_api-25.15.30}/PKG-INFO +5 -5
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/README.md +1 -1
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/IDENTITY.md +2 -3
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent.py +1 -1
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/mcp.py +6 -322
- {gitlab_api-25.15.27 → gitlab_api-25.15.30/gitlab_api.egg-info}/PKG-INFO +5 -5
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api.egg-info/SOURCES.txt +0 -1
- gitlab_api-25.15.30/gitlab_api.egg-info/requires.txt +13 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/pyproject.toml +4 -4
- gitlab_api-25.15.27/gitlab_api/mcp_config.json +0 -7
- gitlab_api-25.15.27/gitlab_api.egg-info/requires.txt +0 -13
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/LICENSE +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/MANIFEST.in +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/__init__.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/__main__.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/AGENTS.md +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/CRON.md +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/CRON_LOG.md +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/HEARTBEAT.md +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/MEMORY.md +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/USER.md +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/mcp_config.json +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/agent/templates.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/auth.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/gitlab_api.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/gitlab_gql.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/gitlab_input_models.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api/gitlab_response_models.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api.egg-info/dependency_links.txt +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api.egg-info/entry_points.txt +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/gitlab_api.egg-info/top_level.txt +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/requirements.txt +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/scripts/validate_a2a_agent.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/scripts/validate_agent.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/setup.cfg +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/tests/test_gitlab_a2a_validation.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/tests/test_gitlab_api.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/tests/test_gitlab_mcp_validation.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/tests/test_gitlab_models.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/tests/test_verify_agent.py +0 -0
- {gitlab_api-25.15.27 → gitlab_api-25.15.30}/tests/verify_a2a_queries.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-api
|
|
3
|
-
Version: 25.15.
|
|
3
|
+
Version: 25.15.30
|
|
4
4
|
Summary: GitLab API + MCP Server + A2A Server
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,11 +12,11 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-utilities>=0.2.
|
|
15
|
+
Requires-Dist: agent-utilities>=0.2.15
|
|
16
16
|
Provides-Extra: mcp
|
|
17
|
-
Requires-Dist: agent-utilities[mcp]>=0.2.
|
|
17
|
+
Requires-Dist: agent-utilities[mcp]>=0.2.15; extra == "mcp"
|
|
18
18
|
Provides-Extra: agent
|
|
19
|
-
Requires-Dist: agent-utilities[agent,logfire]>=0.2.
|
|
19
|
+
Requires-Dist: agent-utilities[agent,logfire]>=0.2.15; extra == "agent"
|
|
20
20
|
Provides-Extra: gql
|
|
21
21
|
Requires-Dist: gql>=4.0.0; extra == "gql"
|
|
22
22
|
Provides-Extra: all
|
|
@@ -46,7 +46,7 @@ Dynamic: license-file
|
|
|
46
46
|

|
|
47
47
|

|
|
48
48
|
|
|
49
|
-
*Version: 25.15.
|
|
49
|
+
*Version: 25.15.30*
|
|
50
50
|
|
|
51
51
|
## Overview
|
|
52
52
|
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
### System Prompt
|
|
9
9
|
You are the GitLab Agent.
|
|
10
|
-
You must always first run list_skills
|
|
11
|
-
|
|
12
|
-
Check the `mcp-client` reference documentation for `gitlab-api.md` to discover the exact tags and tools available for your capabilities.
|
|
10
|
+
You must always first run `list_skills` to show all skills.
|
|
11
|
+
Then, use the `mcp-client` universal skill and check the reference documentation for `gitlab-api.md` to discover the exact tags and tools available for your capabilities.
|
|
13
12
|
|
|
14
13
|
### Capabilities
|
|
15
14
|
- **MCP Operations**: Leverage the `mcp-client` skill to interact with the target MCP server. Refer to `gitlab-api.md` for specific tool capabilities.
|
|
@@ -7,33 +7,20 @@ import sys
|
|
|
7
7
|
import logging
|
|
8
8
|
from typing import Optional, List, Dict, Union, Any
|
|
9
9
|
|
|
10
|
-
import requests
|
|
11
10
|
from pydantic import Field
|
|
12
|
-
from eunomia_mcp.middleware import EunomiaMcpMiddleware
|
|
13
11
|
from fastmcp import FastMCP, Context
|
|
14
|
-
from fastmcp.server.auth.oidc_proxy import OIDCProxy
|
|
15
|
-
from fastmcp.server.auth import OAuthProxy, RemoteAuthProvider
|
|
16
|
-
from fastmcp.server.auth.providers.jwt import JWTVerifier, StaticTokenVerifier
|
|
17
|
-
from fastmcp.server.middleware.logging import LoggingMiddleware
|
|
18
|
-
from fastmcp.server.middleware.timing import TimingMiddleware
|
|
19
|
-
from fastmcp.server.middleware.rate_limiting import RateLimitingMiddleware
|
|
20
|
-
from fastmcp.server.middleware.error_handling import ErrorHandlingMiddleware
|
|
21
12
|
from fastmcp.utilities.logging import get_logger
|
|
22
13
|
from gitlab_api.gitlab_response_models import Response
|
|
23
14
|
from agent_utilities.base_utilities import to_boolean
|
|
24
15
|
from agent_utilities.mcp_utilities import (
|
|
25
|
-
|
|
16
|
+
create_mcp_server,
|
|
26
17
|
config,
|
|
27
18
|
)
|
|
28
|
-
from agent_utilities.middlewares import (
|
|
29
|
-
UserTokenMiddleware,
|
|
30
|
-
JWTClaimsLoggingMiddleware,
|
|
31
|
-
)
|
|
32
19
|
from gitlab_api.auth import get_client
|
|
33
20
|
from starlette.requests import Request
|
|
34
21
|
from starlette.responses import JSONResponse
|
|
35
22
|
|
|
36
|
-
__version__ = "25.15.
|
|
23
|
+
__version__ = "25.15.30"
|
|
37
24
|
print(f"Gitlab MCP v{__version__}")
|
|
38
25
|
|
|
39
26
|
logger = get_logger(name="mcp_server")
|
|
@@ -6484,317 +6471,14 @@ def register_prompts(mcp: FastMCP):
|
|
|
6484
6471
|
|
|
6485
6472
|
|
|
6486
6473
|
def mcp_server() -> None:
|
|
6487
|
-
"""Run the GitLab MCP server with specified transport and connection parameters.
|
|
6488
|
-
|
|
6489
|
-
This function parses command-line arguments to configure and start the MCP server for GitLab API interactions.
|
|
6490
|
-
It supports stdio or TCP transport modes and exits on invalid arguments or help requests.
|
|
6491
|
-
|
|
6492
|
-
Example:
|
|
6493
|
-
$ python gitlab_api_mcp.py --transport streamable-http --host localhost --port 5000
|
|
6494
|
-
"""
|
|
6495
6474
|
load_dotenv(find_dotenv())
|
|
6496
|
-
parser = create_mcp_parser()
|
|
6497
|
-
parser.description = "GitLab MCP Server"
|
|
6498
|
-
args = parser.parse_args()
|
|
6499
|
-
|
|
6500
|
-
if hasattr(args, "help") and args.help:
|
|
6501
|
-
|
|
6502
|
-
parser.print_help()
|
|
6503
6475
|
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
sys.exit(1)
|
|
6509
|
-
|
|
6510
|
-
config["enable_delegation"] = args.enable_delegation
|
|
6511
|
-
config["audience"] = args.audience or config["audience"]
|
|
6512
|
-
config["delegated_scopes"] = args.delegated_scopes or config["delegated_scopes"]
|
|
6513
|
-
config["oidc_config_url"] = args.oidc_config_url or config["oidc_config_url"]
|
|
6514
|
-
config["oidc_client_id"] = args.oidc_client_id or config["oidc_client_id"]
|
|
6515
|
-
config["oidc_client_secret"] = (
|
|
6516
|
-
args.oidc_client_secret or config["oidc_client_secret"]
|
|
6517
|
-
)
|
|
6518
|
-
|
|
6519
|
-
if config["enable_delegation"]:
|
|
6520
|
-
if args.auth_type != "oidc-proxy":
|
|
6521
|
-
logger.error("Token delegation requires auth-type=oidc-proxy")
|
|
6522
|
-
sys.exit(1)
|
|
6523
|
-
if not config["audience"]:
|
|
6524
|
-
logger.error("audience is required for delegation")
|
|
6525
|
-
sys.exit(1)
|
|
6526
|
-
if not all(
|
|
6527
|
-
[
|
|
6528
|
-
config["oidc_config_url"],
|
|
6529
|
-
config["oidc_client_id"],
|
|
6530
|
-
config["oidc_client_secret"],
|
|
6531
|
-
]
|
|
6532
|
-
):
|
|
6533
|
-
logger.error(
|
|
6534
|
-
"Delegation requires complete OIDC configuration (oidc-config-url, oidc-client-id, oidc-client-secret)"
|
|
6535
|
-
)
|
|
6536
|
-
sys.exit(1)
|
|
6537
|
-
|
|
6538
|
-
try:
|
|
6539
|
-
logger.info(
|
|
6540
|
-
"Fetching OIDC configuration",
|
|
6541
|
-
extra={"oidc_config_url": config["oidc_config_url"]},
|
|
6542
|
-
)
|
|
6543
|
-
oidc_config_resp = requests.get(config["oidc_config_url"])
|
|
6544
|
-
oidc_config_resp.raise_for_status()
|
|
6545
|
-
oidc_config = oidc_config_resp.json()
|
|
6546
|
-
config["token_endpoint"] = oidc_config.get("token_endpoint")
|
|
6547
|
-
if not config["token_endpoint"]:
|
|
6548
|
-
logger.error("No token_endpoint found in OIDC configuration")
|
|
6549
|
-
raise ValueError("No token_endpoint found in OIDC configuration")
|
|
6550
|
-
logger.info(
|
|
6551
|
-
"OIDC configuration fetched successfully",
|
|
6552
|
-
extra={"token_endpoint": config["token_endpoint"]},
|
|
6553
|
-
)
|
|
6554
|
-
except Exception as e:
|
|
6555
|
-
print(f"Failed to fetch OIDC configuration: {e}")
|
|
6556
|
-
logger.error(
|
|
6557
|
-
"Failed to fetch OIDC configuration",
|
|
6558
|
-
extra={"error_type": type(e).__name__, "error_message": str(e)},
|
|
6559
|
-
)
|
|
6560
|
-
sys.exit(1)
|
|
6561
|
-
|
|
6562
|
-
auth = None
|
|
6563
|
-
allowed_uris = (
|
|
6564
|
-
args.allowed_client_redirect_uris.split(",")
|
|
6565
|
-
if args.allowed_client_redirect_uris
|
|
6566
|
-
else None
|
|
6476
|
+
args, mcp, middlewares = create_mcp_server(
|
|
6477
|
+
name="GitLab",
|
|
6478
|
+
version=__version__,
|
|
6479
|
+
instructions="GitLab API MCP Server - Manage projects, issues, merge requests, branches, and more.",
|
|
6567
6480
|
)
|
|
6568
6481
|
|
|
6569
|
-
if args.auth_type == "none":
|
|
6570
|
-
auth = None
|
|
6571
|
-
elif args.auth_type == "static":
|
|
6572
|
-
auth = StaticTokenVerifier(
|
|
6573
|
-
tokens={
|
|
6574
|
-
"test-token": {"client_id": "test-user", "scopes": ["read", "write"]},
|
|
6575
|
-
"admin-token": {"client_id": "admin", "scopes": ["admin"]},
|
|
6576
|
-
}
|
|
6577
|
-
)
|
|
6578
|
-
elif args.auth_type == "jwt":
|
|
6579
|
-
jwks_uri = args.token_jwks_uri or os.getenv("FASTMCP_SERVER_AUTH_JWT_JWKS_URI")
|
|
6580
|
-
issuer = args.token_issuer or os.getenv("FASTMCP_SERVER_AUTH_JWT_ISSUER")
|
|
6581
|
-
audience = args.token_audience or os.getenv("FASTMCP_SERVER_AUTH_JWT_AUDIENCE")
|
|
6582
|
-
algorithm = args.token_algorithm
|
|
6583
|
-
secret_or_key = args.token_secret or args.token_public_key
|
|
6584
|
-
public_key_pem = None
|
|
6585
|
-
|
|
6586
|
-
if not (jwks_uri or secret_or_key):
|
|
6587
|
-
logger.error(
|
|
6588
|
-
"JWT auth requires either --token-jwks-uri or --token-secret/--token-public-key"
|
|
6589
|
-
)
|
|
6590
|
-
sys.exit(1)
|
|
6591
|
-
if not (issuer and audience):
|
|
6592
|
-
logger.error("JWT requires --token-issuer and --token-audience")
|
|
6593
|
-
sys.exit(1)
|
|
6594
|
-
|
|
6595
|
-
if args.token_public_key and os.path.isfile(args.token_public_key):
|
|
6596
|
-
try:
|
|
6597
|
-
with open(args.token_public_key, "r") as f:
|
|
6598
|
-
public_key_pem = f.read()
|
|
6599
|
-
logger.info(f"Loaded static public key from {args.token_public_key}")
|
|
6600
|
-
except Exception as e:
|
|
6601
|
-
print(f"Failed to read public key file: {e}")
|
|
6602
|
-
logger.error(f"Failed to read public key file: {e}")
|
|
6603
|
-
sys.exit(1)
|
|
6604
|
-
elif args.token_public_key:
|
|
6605
|
-
public_key_pem = args.token_public_key
|
|
6606
|
-
|
|
6607
|
-
if jwks_uri and (algorithm or secret_or_key):
|
|
6608
|
-
logger.warning(
|
|
6609
|
-
"JWKS mode ignores --token-algorithm and --token-secret/--token-public-key"
|
|
6610
|
-
)
|
|
6611
|
-
|
|
6612
|
-
if algorithm and algorithm.startswith("HS"):
|
|
6613
|
-
if not secret_or_key:
|
|
6614
|
-
logger.error(f"HMAC algorithm {algorithm} requires --token-secret")
|
|
6615
|
-
sys.exit(1)
|
|
6616
|
-
if jwks_uri:
|
|
6617
|
-
logger.error("Cannot use --token-jwks-uri with HMAC")
|
|
6618
|
-
sys.exit(1)
|
|
6619
|
-
public_key = secret_or_key
|
|
6620
|
-
else:
|
|
6621
|
-
public_key = public_key_pem
|
|
6622
|
-
|
|
6623
|
-
required_scopes = None
|
|
6624
|
-
if args.required_scopes:
|
|
6625
|
-
required_scopes = [
|
|
6626
|
-
s.strip() for s in args.required_scopes.split(",") if s.strip()
|
|
6627
|
-
]
|
|
6628
|
-
|
|
6629
|
-
try:
|
|
6630
|
-
auth = JWTVerifier(
|
|
6631
|
-
jwks_uri=jwks_uri,
|
|
6632
|
-
public_key=public_key,
|
|
6633
|
-
issuer=issuer,
|
|
6634
|
-
audience=audience,
|
|
6635
|
-
algorithm=(
|
|
6636
|
-
algorithm if algorithm and algorithm.startswith("HS") else None
|
|
6637
|
-
),
|
|
6638
|
-
required_scopes=required_scopes,
|
|
6639
|
-
)
|
|
6640
|
-
logger.info(
|
|
6641
|
-
"JWTVerifier configured",
|
|
6642
|
-
extra={
|
|
6643
|
-
"mode": (
|
|
6644
|
-
"JWKS"
|
|
6645
|
-
if jwks_uri
|
|
6646
|
-
else (
|
|
6647
|
-
"HMAC"
|
|
6648
|
-
if algorithm and algorithm.startswith("HS")
|
|
6649
|
-
else "Static Key"
|
|
6650
|
-
)
|
|
6651
|
-
),
|
|
6652
|
-
"algorithm": algorithm,
|
|
6653
|
-
"required_scopes": required_scopes,
|
|
6654
|
-
},
|
|
6655
|
-
)
|
|
6656
|
-
except Exception as e:
|
|
6657
|
-
print(f"Failed to initialize JWTVerifier: {e}")
|
|
6658
|
-
logger.error(f"Failed to initialize JWTVerifier: {e}")
|
|
6659
|
-
sys.exit(1)
|
|
6660
|
-
elif args.auth_type == "oauth-proxy":
|
|
6661
|
-
if not (
|
|
6662
|
-
args.oauth_upstream_auth_endpoint
|
|
6663
|
-
and args.oauth_upstream_token_endpoint
|
|
6664
|
-
and args.oauth_upstream_client_id
|
|
6665
|
-
and args.oauth_upstream_client_secret
|
|
6666
|
-
and args.oauth_base_url
|
|
6667
|
-
and args.token_jwks_uri
|
|
6668
|
-
and args.token_issuer
|
|
6669
|
-
and args.token_audience
|
|
6670
|
-
):
|
|
6671
|
-
print(
|
|
6672
|
-
"oauth-proxy requires oauth-upstream-auth-endpoint, oauth-upstream-token-endpoint, "
|
|
6673
|
-
"oauth-upstream-client-id, oauth-upstream-client-secret, oauth-base-url, token-jwks-uri, "
|
|
6674
|
-
"token-issuer, token-audience"
|
|
6675
|
-
)
|
|
6676
|
-
logger.error(
|
|
6677
|
-
"oauth-proxy requires oauth-upstream-auth-endpoint, oauth-upstream-token-endpoint, "
|
|
6678
|
-
"oauth-upstream-client-id, oauth-upstream-client-secret, oauth-base-url, token-jwks-uri, "
|
|
6679
|
-
"token-issuer, token-audience",
|
|
6680
|
-
extra={
|
|
6681
|
-
"auth_endpoint": args.oauth_upstream_auth_endpoint,
|
|
6682
|
-
"token_endpoint": args.oauth_upstream_token_endpoint,
|
|
6683
|
-
"client_id": args.oauth_upstream_client_id,
|
|
6684
|
-
"base_url": args.oauth_base_url,
|
|
6685
|
-
"jwks_uri": args.token_jwks_uri,
|
|
6686
|
-
"issuer": args.token_issuer,
|
|
6687
|
-
"audience": args.token_audience,
|
|
6688
|
-
},
|
|
6689
|
-
)
|
|
6690
|
-
sys.exit(1)
|
|
6691
|
-
token_verifier = JWTVerifier(
|
|
6692
|
-
jwks_uri=args.token_jwks_uri,
|
|
6693
|
-
issuer=args.token_issuer,
|
|
6694
|
-
audience=args.token_audience,
|
|
6695
|
-
)
|
|
6696
|
-
auth = OAuthProxy(
|
|
6697
|
-
upstream_authorization_endpoint=args.oauth_upstream_auth_endpoint,
|
|
6698
|
-
upstream_token_endpoint=args.oauth_upstream_token_endpoint,
|
|
6699
|
-
upstream_client_id=args.oauth_upstream_client_id,
|
|
6700
|
-
upstream_client_secret=args.oauth_upstream_client_secret,
|
|
6701
|
-
token_verifier=token_verifier,
|
|
6702
|
-
base_url=args.oauth_base_url,
|
|
6703
|
-
allowed_client_redirect_uris=allowed_uris,
|
|
6704
|
-
)
|
|
6705
|
-
elif args.auth_type == "oidc-proxy":
|
|
6706
|
-
if not (
|
|
6707
|
-
args.oidc_config_url
|
|
6708
|
-
and args.oidc_client_id
|
|
6709
|
-
and args.oidc_client_secret
|
|
6710
|
-
and args.oidc_base_url
|
|
6711
|
-
):
|
|
6712
|
-
logger.error(
|
|
6713
|
-
"oidc-proxy requires oidc-config-url, oidc-client-id, oidc-client-secret, oidc-base-url",
|
|
6714
|
-
extra={
|
|
6715
|
-
"config_url": args.oidc_config_url,
|
|
6716
|
-
"client_id": args.oidc_client_id,
|
|
6717
|
-
"base_url": args.oidc_base_url,
|
|
6718
|
-
},
|
|
6719
|
-
)
|
|
6720
|
-
sys.exit(1)
|
|
6721
|
-
auth = OIDCProxy(
|
|
6722
|
-
config_url=args.oidc_config_url,
|
|
6723
|
-
client_id=args.oidc_client_id,
|
|
6724
|
-
client_secret=args.oidc_client_secret,
|
|
6725
|
-
base_url=args.oidc_base_url,
|
|
6726
|
-
allowed_client_redirect_uris=allowed_uris,
|
|
6727
|
-
)
|
|
6728
|
-
elif args.auth_type == "remote-oauth":
|
|
6729
|
-
if not (
|
|
6730
|
-
args.remote_auth_servers
|
|
6731
|
-
and args.remote_base_url
|
|
6732
|
-
and args.token_jwks_uri
|
|
6733
|
-
and args.token_issuer
|
|
6734
|
-
and args.token_audience
|
|
6735
|
-
):
|
|
6736
|
-
logger.error(
|
|
6737
|
-
"remote-oauth requires remote-auth-servers, remote-base-url, token-jwks-uri, token-issuer, token-audience",
|
|
6738
|
-
extra={
|
|
6739
|
-
"auth_servers": args.remote_auth_servers,
|
|
6740
|
-
"base_url": args.remote_base_url,
|
|
6741
|
-
"jwks_uri": args.token_jwks_uri,
|
|
6742
|
-
"issuer": args.token_issuer,
|
|
6743
|
-
"audience": args.token_audience,
|
|
6744
|
-
},
|
|
6745
|
-
)
|
|
6746
|
-
sys.exit(1)
|
|
6747
|
-
auth_servers = [url.strip() for url in args.remote_auth_servers.split(",")]
|
|
6748
|
-
token_verifier = JWTVerifier(
|
|
6749
|
-
jwks_uri=args.token_jwks_uri,
|
|
6750
|
-
issuer=args.token_issuer,
|
|
6751
|
-
audience=args.token_audience,
|
|
6752
|
-
)
|
|
6753
|
-
auth = RemoteAuthProvider(
|
|
6754
|
-
token_verifier=token_verifier,
|
|
6755
|
-
authorization_servers=auth_servers,
|
|
6756
|
-
base_url=args.remote_base_url,
|
|
6757
|
-
)
|
|
6758
|
-
|
|
6759
|
-
middlewares: List[
|
|
6760
|
-
Union[
|
|
6761
|
-
UserTokenMiddleware,
|
|
6762
|
-
ErrorHandlingMiddleware,
|
|
6763
|
-
RateLimitingMiddleware,
|
|
6764
|
-
TimingMiddleware,
|
|
6765
|
-
LoggingMiddleware,
|
|
6766
|
-
JWTClaimsLoggingMiddleware,
|
|
6767
|
-
EunomiaMcpMiddleware,
|
|
6768
|
-
]
|
|
6769
|
-
] = [
|
|
6770
|
-
ErrorHandlingMiddleware(include_traceback=True, transform_errors=True),
|
|
6771
|
-
RateLimitingMiddleware(max_requests_per_second=10.0, burst_capacity=20),
|
|
6772
|
-
TimingMiddleware(),
|
|
6773
|
-
LoggingMiddleware(),
|
|
6774
|
-
JWTClaimsLoggingMiddleware(),
|
|
6775
|
-
]
|
|
6776
|
-
if config["enable_delegation"] or args.auth_type == "jwt":
|
|
6777
|
-
middlewares.insert(0, UserTokenMiddleware(config=config))
|
|
6778
|
-
|
|
6779
|
-
if args.eunomia_type in ["embedded", "remote"]:
|
|
6780
|
-
try:
|
|
6781
|
-
from eunomia_mcp import create_eunomia_middleware
|
|
6782
|
-
|
|
6783
|
-
policy_file = args.eunomia_policy_file or "mcp_policies.json"
|
|
6784
|
-
eunomia_endpoint = (
|
|
6785
|
-
args.eunomia_remote_url if args.eunomia_type == "remote" else None
|
|
6786
|
-
)
|
|
6787
|
-
eunomia_mw = create_eunomia_middleware(
|
|
6788
|
-
policy_file=policy_file, eunomia_endpoint=eunomia_endpoint
|
|
6789
|
-
)
|
|
6790
|
-
middlewares.append(eunomia_mw)
|
|
6791
|
-
logger.info(f"Eunomia middleware enabled ({args.eunomia_type})")
|
|
6792
|
-
except Exception as e:
|
|
6793
|
-
print(f"Failed to load Eunomia middleware: {e}")
|
|
6794
|
-
logger.error("Failed to load Eunomia middleware", extra={"error": str(e)})
|
|
6795
|
-
sys.exit(1)
|
|
6796
|
-
|
|
6797
|
-
mcp = FastMCP("GitLab", auth=auth)
|
|
6798
6482
|
DEFAULT_MISCTOOL = to_boolean(os.getenv("MISCTOOL", "True"))
|
|
6799
6483
|
if DEFAULT_MISCTOOL:
|
|
6800
6484
|
register_misc_tools(mcp)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-api
|
|
3
|
-
Version: 25.15.
|
|
3
|
+
Version: 25.15.30
|
|
4
4
|
Summary: GitLab API + MCP Server + A2A Server
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,11 +12,11 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.10
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-utilities>=0.2.
|
|
15
|
+
Requires-Dist: agent-utilities>=0.2.15
|
|
16
16
|
Provides-Extra: mcp
|
|
17
|
-
Requires-Dist: agent-utilities[mcp]>=0.2.
|
|
17
|
+
Requires-Dist: agent-utilities[mcp]>=0.2.15; extra == "mcp"
|
|
18
18
|
Provides-Extra: agent
|
|
19
|
-
Requires-Dist: agent-utilities[agent,logfire]>=0.2.
|
|
19
|
+
Requires-Dist: agent-utilities[agent,logfire]>=0.2.15; extra == "agent"
|
|
20
20
|
Provides-Extra: gql
|
|
21
21
|
Requires-Dist: gql>=4.0.0; extra == "gql"
|
|
22
22
|
Provides-Extra: all
|
|
@@ -46,7 +46,7 @@ Dynamic: license-file
|
|
|
46
46
|

|
|
47
47
|

|
|
48
48
|
|
|
49
|
-
*Version: 25.15.
|
|
49
|
+
*Version: 25.15.30*
|
|
50
50
|
|
|
51
51
|
## Overview
|
|
52
52
|
|
|
@@ -12,7 +12,6 @@ gitlab_api/gitlab_gql.py
|
|
|
12
12
|
gitlab_api/gitlab_input_models.py
|
|
13
13
|
gitlab_api/gitlab_response_models.py
|
|
14
14
|
gitlab_api/mcp.py
|
|
15
|
-
gitlab_api/mcp_config.json
|
|
16
15
|
gitlab_api.egg-info/PKG-INFO
|
|
17
16
|
gitlab_api.egg-info/SOURCES.txt
|
|
18
17
|
gitlab_api.egg-info/dependency_links.txt
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gitlab-api"
|
|
7
|
-
version = "25.15.
|
|
7
|
+
version = "25.15.30"
|
|
8
8
|
description = "GitLab API + MCP Server + A2A Server"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [{ name = "Audel Rouhi", email = "knucklessg1@gmail.com" }]
|
|
@@ -17,13 +17,13 @@ classifiers = [
|
|
|
17
17
|
"Programming Language :: Python :: 3"]
|
|
18
18
|
requires-python = ">=3.10"
|
|
19
19
|
dependencies = [
|
|
20
|
-
"agent-utilities>=0.2.
|
|
20
|
+
"agent-utilities>=0.2.15"]
|
|
21
21
|
[project.optional-dependencies]
|
|
22
22
|
mcp = [
|
|
23
|
-
"agent-utilities[mcp]>=0.2.
|
|
23
|
+
"agent-utilities[mcp]>=0.2.15"]
|
|
24
24
|
|
|
25
25
|
agent = [
|
|
26
|
-
"agent-utilities[agent,logfire]>=0.2.
|
|
26
|
+
"agent-utilities[agent,logfire]>=0.2.15"]
|
|
27
27
|
|
|
28
28
|
gql = [
|
|
29
29
|
"gql>=4.0.0"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|