Skip to content

Commit 02a54c2

Browse files
committed
fix(native): register reflection/resource metadata so the binary works
The root cause of `auth() failed: HTTP 0` was never TLS. GraalVM native images need reflection metadata for every Jackson-(de)serialized type; without it, deserializing the auth response throws InvalidDefinitionException (an IOException), which the OpenAPI client wraps as ApiException code 0. The MCP layer was equally broken: McpSchema record components were unregistered, so even a stdio `initialize` crashed with UnsupportedFeatureError. - Add reflect-config.json generated with the GraalVM tracing agent across full MCP sessions (stub + live API), plus wholesale registration of all McpSchema$*, api.client.model.* and mcp.model.* types. - Replace reachability-metadata.json (unified format, ignored by GraalVM for JDK 21) with classic reflect-config.json / resource-config.json, processed by every GraalVM version. - Include logback.xml in the image: native logs were going to stdout with the default pattern, corrupting the MCP stdio protocol; they now go to stderr. - Drop the obsolete "Sync OS CA certificates" CI step; the WE1 intermediate is now bundled in-image (see previous commit), making the cacerts surgery moot. Verified end-to-end on macOS arm64: --help, tools/list and live tool calls. Bumps version to 0.3.3.
1 parent 8182d3c commit 02a54c2

7 files changed

Lines changed: 1947 additions & 77 deletions

File tree

.github/workflows/ci.yml

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -47,53 +47,6 @@ jobs:
4747
java-version: '21'
4848
distribution: 'graalvm'
4949
cache: 'maven'
50-
- name: Sync OS CA certificates into GraalVM JDK
51-
shell: bash
52-
run: |
53-
CACERTS="$JAVA_HOME/lib/security/cacerts"
54-
55-
# 1. Import root CAs from the OS trust store
56-
if [[ "$RUNNER_OS" == "macOS" ]]; then
57-
security export -t certs -f pemseq \
58-
-k /System/Library/Keychains/SystemRootCertificates.keychain \
59-
> /tmp/os-roots.pem
60-
elif [[ "$RUNNER_OS" == "Linux" ]]; then
61-
cat /etc/ssl/certs/*.pem > /tmp/os-roots.pem 2>/dev/null || true
62-
fi
63-
if [[ -f /tmp/os-roots.pem ]]; then
64-
awk '/-----BEGIN CERTIFICATE-----/{n++; close(f); f="/tmp/ca-"n".pem"} {print > f}' \
65-
/tmp/os-roots.pem
66-
imported=0
67-
for f in /tmp/ca-*.pem; do
68-
[[ -s "$f" ]] || continue
69-
hash=$(openssl x509 -noout -hash -in "$f" 2>/dev/null) || continue
70-
keytool -importcert -noprompt -trustcacerts \
71-
-alias "os-root-${hash}" \
72-
-keystore "$CACERTS" -storepass changeit \
73-
-file "$f" 2>/dev/null && ((imported++)) || true
74-
done
75-
echo "Imported $imported root CAs from OS"
76-
fi
77-
78-
# 2. Fetch any intermediate CAs the server omits from its TLS chain (via AIA).
79-
# GraalVM native images cannot chase AIA at runtime; bake the intermediates in.
80-
AIA_URL=$(echo | openssl s_client -connect api.qtsurfer.net:443 \
81-
-servername api.qtsurfer.net 2>/dev/null \
82-
| openssl x509 -noout -text 2>/dev/null \
83-
| grep "CA Issuers" | grep -o 'http[^ ]*' | head -1)
84-
if [[ -n "$AIA_URL" ]]; then
85-
curl -sf "$AIA_URL" -o /tmp/intermediate.der
86-
openssl x509 -inform der -in /tmp/intermediate.der -out /tmp/intermediate.pem 2>/dev/null \
87-
|| cp /tmp/intermediate.der /tmp/intermediate.pem
88-
hash=$(openssl x509 -noout -hash -in /tmp/intermediate.pem 2>/dev/null)
89-
subj=$(openssl x509 -noout -subject -in /tmp/intermediate.pem 2>/dev/null)
90-
keytool -importcert -noprompt -trustcacerts \
91-
-alias "intermediate-${hash}" \
92-
-keystore "$CACERTS" -storepass changeit \
93-
-file /tmp/intermediate.pem 2>/dev/null \
94-
&& echo "Imported intermediate CA: ${subj}" \
95-
|| echo "Intermediate already trusted: ${subj}"
96-
fi
9750
- name: Set up MSVC (required by GraalVM native-image on Windows)
9851
if: matrix.os == 'windows-latest'
9952
uses: ilammy/msvc-dev-cmd@v1

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66

77
## [Unreleased]
88

9+
## [0.3.3] — 2026-06-13
10+
11+
### Fixed 🐛
12+
13+
- **Native binary was non-functional beyond `--help`** — root cause of the `auth() failed: HTTP 0` errors finally identified: it was never TLS. GraalVM native images need reflection metadata for every Jackson-(de)serialized type; without it, deserializing the auth response throws `InvalidDefinitionException` (an `IOException` subclass), which the OpenAPI client wraps as `ApiException` with code 0. The MCP layer was equally broken: `McpSchema` record components were not registered, so even a stdio `initialize` crashed with `UnsupportedFeatureError`.
14+
- Added `reflect-config.json` generated with the GraalVM tracing agent across full MCP sessions (stub + live API), plus wholesale registration of all `McpSchema$*`, `api.client.model.*`, and `mcp.model.*` types.
15+
- Replaced `reachability-metadata.json` (the unified format, ignored by GraalVM for JDK 21) with classic-format `reflect-config.json`/`resource-config.json`, which all GraalVM versions process.
16+
- `logback.xml` is now included in the image: native binary logs went to **stdout** with the default pattern, corrupting the MCP stdio protocol; they now go to stderr as configured.
17+
- Verified end-to-end on macOS arm64: authentication, `tools/list`, and live tool calls against the production API.
18+
919
## [0.3.2] — 2026-06-13
1020

1121
### Fixed 🐛

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ The installer detects your platform and picks the right delivery:
4141
Pin a version or override the destination:
4242

4343
```bash
44-
VERSION=0.3.2 INSTALL_DIR=~/.local/bin \
44+
VERSION=0.3.3 INSTALL_DIR=~/.local/bin \
4545
curl -fsSL https://raw.githubusercontent.com/QTSurfer/mcp-java/main/install.sh | bash
4646
```
4747

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
<groupId>com.qtsurfer</groupId>
77
<artifactId>mcp-java</artifactId>
8-
<version>0.3.2</version>
8+
<version>0.3.3</version>
99
<packaging>jar</packaging>
1010
<name>qtsurfer-mcp-java</name>
1111

0 commit comments

Comments
 (0)