feat: add mTLS client certificate support #232

Open
berzdev wants to merge 3 commits from berzdev/feat/mtls-client-cert-support into main
berzdev commented 2026-06-07 20:09:52 +00:00 (Migrated from codeberg.org)

Add -tls-cert / -tls-key flags and FORGEJO_TLS_CERT / FORGEJO_TLS_KEY
env vars to configure a TLS client certificate for Forgejo instances
that require mutual TLS authentication at the network level.

When both cert and key are provided, a custom http.Client with the
client certificate is injected into the Forgejo SDK via SetHTTPClient.
If not set, behaviour is unchanged.

Example:
forgejo-mcp -t stdio -url https://git.example.com
-tls-cert ~/.config/mtls/client.crt.pem
-tls-key ~/.config/mtls/client.key.pem

Or via env vars:
FORGEJO_TLS_CERT=/.config/mtls/client.crt.pem
FORGEJO_TLS_KEY=
/.config/mtls/client.key.pem
forgejo-mcp -t stdio -url https://git.example.com

Add -tls-cert / -tls-key flags and FORGEJO_TLS_CERT / FORGEJO_TLS_KEY env vars to configure a TLS client certificate for Forgejo instances that require mutual TLS authentication at the network level. When both cert and key are provided, a custom http.Client with the client certificate is injected into the Forgejo SDK via SetHTTPClient. If not set, behaviour is unchanged. Example: forgejo-mcp -t stdio -url https://git.example.com \ -tls-cert ~/.config/mtls/client.crt.pem \ -tls-key ~/.config/mtls/client.key.pem Or via env vars: FORGEJO_TLS_CERT=~/.config/mtls/client.crt.pem \ FORGEJO_TLS_KEY=~/.config/mtls/client.key.pem \ forgejo-mcp -t stdio -url https://git.example.com
op1st-gitops commented 2026-06-07 20:10:00 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code is skipping this commit.
User berzdev is not allowed to trigger CI via pull_request in this repo.

op1st Pipelines as Code is skipping this commit. User berzdev is not allowed to trigger CI via pull_request in this repo.
goern commented 2026-06-07 21:36:22 +00:00 (Migrated from codeberg.org)

/ok-to-test

/ok-to-test
op1st-gitops commented 2026-06-07 21:36:26 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request-6ntwt is running.

Starting Pipelinerun forgejo-mcp-on-pull-request-6ntwt in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines forgejo-mcp-on-pull-request-6ntwt -f

op1st Pipelines as Code/forgejo-mcp-on-pull-request-6ntwt is running. Starting Pipelinerun <b>[forgejo-mcp-on-pull-request-6ntwt](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-6ntwt)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-6ntwt) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines forgejo-mcp-on-pull-request-6ntwt -f</code>
op1st-gitops commented 2026-06-07 21:36:27 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans- has failed.
There was an error creating the PipelineRun: forgejo-mcp-code-scans-

cannot use the API on the provider platform to create a in_progress status:

op1st Pipelines as Code/forgejo-mcp-code-scans- has <b>failed</b>. There was an error creating the PipelineRun: <b>forgejo-mcp-code-scans-</b> cannot use the API on the provider platform to create a in_progress status:
op1st-gitops commented 2026-06-07 21:38:14 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request-6ntwt has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 12 seconds

fetch-source

Succeeded 1 minute

build-and-test

Succeeded 17 seconds

commit-title-check

op1st Pipelines as Code/forgejo-mcp-on-pull-request-6ntwt has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-6ntwt">forgejo-mcp-on-pull-request-6ntwt</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>12 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-6ntwt/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>1 minute</td><td> [build-and-test](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-6ntwt/logs/build-and-test) </td></tr> <tr> <td>Succeeded</td> <td>17 seconds</td><td> [commit-title-check](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-6ntwt/logs/commit-title-check) </td></tr> </table>
goern commented 2026-06-09 08:31:21 +00:00 (Migrated from codeberg.org)

@berzdev — thanks for the contribution! Could you have a look at the inline review comments left above? Three issues were flagged in pkg/forgejo/forgejo.go:

  1. Partial config silent ignore (line 18): if only one of --tls-cert / --tls-key is set, mtlsClient() returns nil without logging anything, so mTLS is silently skipped.
  2. Fail-open on cert load error (line 22): LoadX509KeyPair failure logs an error but returns nil, causing the client to connect without mTLS. Should be a hard failure.
  3. Bare http.Transport (line 26): constructing a fresh transport instead of cloning http.DefaultTransport drops proxy support (HTTP_PROXY/HTTPS_PROXY), connection-pool timeouts, and http.Client.Timeout.

Happy to discuss the suggested fixes in the review thread!

@berzdev — thanks for the contribution! Could you have a look at the inline review comments left above? Three issues were flagged in `pkg/forgejo/forgejo.go`: 1. **Partial config silent ignore** (line 18): if only one of `--tls-cert` / `--tls-key` is set, `mtlsClient()` returns `nil` without logging anything, so mTLS is silently skipped. 2. **Fail-open on cert load error** (line 22): `LoadX509KeyPair` failure logs an error but returns `nil`, causing the client to connect without mTLS. Should be a hard failure. 3. **Bare `http.Transport`** (line 26): constructing a fresh transport instead of cloning `http.DefaultTransport` drops proxy support (`HTTP_PROXY`/`HTTPS_PROXY`), connection-pool timeouts, and `http.Client.Timeout`. Happy to discuss the suggested fixes in the review thread!
byteflavour commented 2026-06-09 10:17:09 +00:00 (Migrated from codeberg.org)

Thanks for the contribution, @berzdev! While reviewing the PR, we wanted to bring up a few architectural design points for discussion to see if they might be relevant for your use case or if we should consider adding them to future-proof the implementation:

  1. Custom Root CA Support (e.g., -tls-ca / FORGEJO_TLS_CA):
    In many private or enterprise environments where mTLS is used, the Forgejo instance might run on a private/internal Certificate Authority (CA) rather than a public one. If the system running forgejo-mcp does not trust that private CA, the TLS handshake will fail. Would it be useful to add an optional way to specify a custom server CA certificate to trust? This would avoid having users bypass server verification entirely (e.g. via insecure flags).

  2. Zero-Downtime Certificate Rotation:
    Since forgejo-mcp can run as a long-lived process (like in SSE mode), certificates loaded at startup might eventually expire. In environments where certs are rotated dynamically on disk (like Kubernetes secrets or Vault volume mounts), we could use Go's GetClientCertificate callback in tls.Config instead of a one-time tls.LoadX509KeyPair. This allows reloading rotated certs on the fly without restarting the process. Is this something your deployment environment would benefit from?

  3. Cloud-Native PEM Input (Inline Certificate Data):
    In containerized/serverless environments (like AWS Fargate or Google Cloud Run), mounting files to disk can be tricky. It is often easier to pass the PEM-encoded certificate/key contents directly in environment variables (e.g., FORGEJO_TLS_CERT_DATA). We could potentially support both file paths and raw PEM strings for greater flexibility.

Let us know what you think and what your deployment target looks like!

Thanks for the contribution, @berzdev! While reviewing the PR, we wanted to bring up a few architectural design points for discussion to see if they might be relevant for your use case or if we should consider adding them to future-proof the implementation: 1. **Custom Root CA Support (e.g., `-tls-ca` / `FORGEJO_TLS_CA`)**: In many private or enterprise environments where mTLS is used, the Forgejo instance might run on a private/internal Certificate Authority (CA) rather than a public one. If the system running `forgejo-mcp` does not trust that private CA, the TLS handshake will fail. Would it be useful to add an optional way to specify a custom server CA certificate to trust? This would avoid having users bypass server verification entirely (e.g. via insecure flags). 2. **Zero-Downtime Certificate Rotation**: Since `forgejo-mcp` can run as a long-lived process (like in SSE mode), certificates loaded at startup might eventually expire. In environments where certs are rotated dynamically on disk (like Kubernetes secrets or Vault volume mounts), we could use Go's `GetClientCertificate` callback in `tls.Config` instead of a one-time `tls.LoadX509KeyPair`. This allows reloading rotated certs on the fly without restarting the process. Is this something your deployment environment would benefit from? 3. **Cloud-Native PEM Input (Inline Certificate Data)**: In containerized/serverless environments (like AWS Fargate or Google Cloud Run), mounting files to disk can be tricky. It is often easier to pass the PEM-encoded certificate/key contents directly in environment variables (e.g., `FORGEJO_TLS_CERT_DATA`). We could potentially support both file paths and raw PEM strings for greater flexibility. Let us know what you think and what your deployment target looks like!
op1st-gitops commented 2026-06-26 13:58:03 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans-rnghp is running.

Starting Pipelinerun forgejo-mcp-code-scans-rnghp in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines forgejo-mcp-code-scans-rnghp -f

op1st Pipelines as Code/forgejo-mcp-code-scans-rnghp is running. Starting Pipelinerun <b>[forgejo-mcp-code-scans-rnghp](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-rnghp)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-rnghp) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines forgejo-mcp-code-scans-rnghp -f</code>
op1st-gitops commented 2026-06-26 13:58:03 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request-gnhhs is running.

Starting Pipelinerun forgejo-mcp-on-pull-request-gnhhs in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines forgejo-mcp-on-pull-request-gnhhs -f

op1st Pipelines as Code/forgejo-mcp-on-pull-request-gnhhs is running. Starting Pipelinerun <b>[forgejo-mcp-on-pull-request-gnhhs](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-gnhhs)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-gnhhs) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines forgejo-mcp-on-pull-request-gnhhs -f</code>
op1st-gitops commented 2026-06-26 13:58:26 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans-rnghp has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 13 seconds

fetch-source

Succeeded 7 seconds

gitleaks-version

Succeeded 9 seconds

gitleaks

op1st Pipelines as Code/forgejo-mcp-code-scans-rnghp has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-rnghp">forgejo-mcp-code-scans-rnghp</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>13 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-rnghp/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>7 seconds</td><td> [gitleaks-version](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-rnghp/logs/gitleaks-version) </td></tr> <tr> <td>Succeeded</td> <td>9 seconds</td><td> [gitleaks](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-rnghp/logs/gitleaks) </td></tr> </table>
op1st-gitops commented 2026-06-26 13:59:52 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request-gnhhs has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 10 seconds

fetch-source

Succeeded 1 minute

build-and-test

Succeeded 14 seconds

commit-title-check

op1st Pipelines as Code/forgejo-mcp-on-pull-request-gnhhs has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-gnhhs">forgejo-mcp-on-pull-request-gnhhs</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>10 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-gnhhs/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>1 minute</td><td> [build-and-test](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-gnhhs/logs/build-and-test) </td></tr> <tr> <td>Succeeded</td> <td>14 seconds</td><td> [commit-title-check](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-on-pull-request-gnhhs/logs/commit-title-check) </td></tr> </table>
op1st-gitops commented 2026-06-26 14:16:45 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans-pcknq is running.

Starting Pipelinerun forgejo-mcp-code-scans-pcknq in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines forgejo-mcp-code-scans-pcknq -f

op1st Pipelines as Code/forgejo-mcp-code-scans-pcknq is running. Starting Pipelinerun <b>[forgejo-mcp-code-scans-pcknq](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-pcknq)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-pcknq) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines forgejo-mcp-code-scans-pcknq -f</code>
op1st-gitops commented 2026-06-26 14:16:45 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-on-pull-request- has failed.
There was an error creating the PipelineRun: forgejo-mcp-on-pull-request-

cannot use the API on the provider platform to create a in_progress status:

op1st Pipelines as Code/forgejo-mcp-on-pull-request- has <b>failed</b>. There was an error creating the PipelineRun: <b>forgejo-mcp-on-pull-request-</b> cannot use the API on the provider platform to create a in_progress status:
op1st-gitops commented 2026-06-26 14:17:09 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/forgejo-mcp-code-scans-pcknq has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 13 seconds

fetch-source

Succeeded 7 seconds

gitleaks-version

Succeeded 11 seconds

gitleaks

op1st Pipelines as Code/forgejo-mcp-code-scans-pcknq has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-pcknq">forgejo-mcp-code-scans-pcknq</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>13 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-pcknq/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>7 seconds</td><td> [gitleaks-version](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-pcknq/logs/gitleaks-version) </td></tr> <tr> <td>Succeeded</td> <td>11 seconds</td><td> [gitleaks](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/forgejo-mcp-code-scans-pcknq/logs/gitleaks) </td></tr> </table>
berzdev commented 2026-06-26 14:18:15 +00:00 (Migrated from codeberg.org)

Thanks for the thorough review! I've pushed two follow-up commits addressing all three bugs and adding the custom CA support:

Bug fixes (commit 25fa43a):

  1. Partial config silent ignore → mtlsClient() now calls log.Fatalf if exactly one of --tls-cert / --tls-key is set. No silent skip.
  2. Fail-open on cert load error → LoadX509KeyPair failure now also calls log.Fatalf, matching the existing pattern for singleton client creation. Server aborts startup rather than proceeding without mTLS.
  3. Bare http.Transport → replaced with http.DefaultTransport.(http.Transport).Clone() so proxy env vars, connection-pool settings, timeouts, and HTTP/2 are all preserved. Added Timeout: 30time.Second on the http.Client.

Custom Root CA (commit 952d866, addressing @byteflavour's point 1):

Added -tls-ca / FORGEJO_TLS_CA for specifying a custom CA certificate bundle. Works standalone (server cert verification only) or combined with -tls-cert/-tls-key for full mutual TLS:

mTLS + private CA

forgejo-mcp -t stdio -url https://git.example.com
-tls-cert ~/.config/mtls/client.crt.pem
-tls-key ~/.config/mtls/client.key.pem
-tls-ca ~/.config/mtls/internal-ca.crt.pem

private CA only (no client cert)

FORGEJO_TLS_CA=/etc/ssl/internstdio -urlhttps://git.example.com

On @byteflavour's remaining po

  • Zero-downtime cert rotation use case is static certs, soI'd rather not add that compleas a follow-up issue if there's interest.- Inline PEM via env vars: Samverless, but out of scope forthis PR. Could be a separate contribution.
Thanks for the thorough review! I've pushed two follow-up commits addressing all three bugs and adding the custom CA support: Bug fixes (commit 25fa43a): 1. Partial config silent ignore → mtlsClient() now calls log.Fatalf if exactly one of --tls-cert / --tls-key is set. No silent skip. 2. Fail-open on cert load error → LoadX509KeyPair failure now also calls log.Fatalf, matching the existing pattern for singleton client creation. Server aborts startup rather than proceeding without mTLS. 3. Bare http.Transport → replaced with http.DefaultTransport.(*http.Transport).Clone() so proxy env vars, connection-pool settings, timeouts, and HTTP/2 are all preserved. Added Timeout: 30*time.Second on the http.Client. Custom Root CA (commit 952d866, addressing @byteflavour's point 1): Added -tls-ca / FORGEJO_TLS_CA for specifying a custom CA certificate bundle. Works standalone (server cert verification only) or combined with -tls-cert/-tls-key for full mutual TLS: # mTLS + private CA forgejo-mcp -t stdio -url https://git.example.com \ -tls-cert ~/.config/mtls/client.crt.pem \ -tls-key ~/.config/mtls/client.key.pem \ -tls-ca ~/.config/mtls/internal-ca.crt.pem # private CA only (no client cert) FORGEJO_TLS_CA=/etc/ssl/internstdio -urlhttps://git.example.com On @byteflavour's remaining po - Zero-downtime cert rotation use case is static certs, soI'd rather not add that compleas a follow-up issue if there's interest.- Inline PEM via env vars: Samverless, but out of scope forthis PR. Could be a separate contribution.
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin berzdev/feat/mtls-client-cert-support:berzdev/feat/mtls-client-cert-support
git switch berzdev/feat/mtls-client-cert-support

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff berzdev/feat/mtls-client-cert-support
git switch berzdev/feat/mtls-client-cert-support
git rebase main
git switch main
git merge --ff-only berzdev/feat/mtls-client-cert-support
git switch berzdev/feat/mtls-client-cert-support
git rebase main
git switch main
git merge --no-ff berzdev/feat/mtls-client-cert-support
git switch main
git merge --squash berzdev/feat/mtls-client-cert-support
git switch main
git merge --ff-only berzdev/feat/mtls-client-cert-support
git switch main
git merge berzdev/feat/mtls-client-cert-support
git push origin main
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
agentic-forges/forgejo-mcp!232
No description provided.