Skip to content

Commit 45cbeb6

Browse files
committed
examples(mcp.proxy): swap github upstream to api.githubcopilot.com over TLS
Drops the local github-mcp-server docker service in favor of GitHub's public Streamable HTTP endpoint at https://api.githubcopilot.com/mcp/. Adds a dedicated http→tls→tcp chain for the github route (TLS sni api.githubcopilot.com, trustcacerts for public CA verification, ALPN http/1.1, TCP 443). The everything and time routes keep their existing plain http→tcp path unchanged. Auth-challenge pass-through still works: an unauthenticated call returns GitHub's HTTP 401 / WWW-Authenticate: Bearer through Zilla's mcp(server) which renders the same 4xx + WWW-Authenticate back to the inbound client, courtesy of the McpResetEx bearer propagation that landed in #1796.
1 parent 9594351 commit 45cbeb6

3 files changed

Lines changed: 48 additions & 49 deletions

File tree

examples/mcp.proxy/README.md

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,15 @@ client ──────►│ │
1212
│ ▼ ▼ ▼ │
1313
│ mcp(client) everything mcp(client) time mcp(client) github
1414
│ │ │ │ │
15+
│ ▼ ▼ ▼ │
16+
│ http → http → http → │
17+
│ tcp tcp tls → │
18+
│ tcp:443 │
1519
└──────────────┼─────────────┼─────────────┼─────┘
1620
▼ ▼ ▼
17-
everything:3001 time:3002 github:3003
18-
(reference (mcp-proxy (github-mcp-
19-
server) + uvx) server http)
21+
everything:3001 time:3002 api.githubcopilot.com:443
22+
(reference (mcp-proxy (GitHub Copilot
23+
server) + uvx) Streamable HTTP)
2024
```
2125

2226
The proxy demonstrates, in one configuration:
@@ -35,32 +39,33 @@ The proxy demonstrates, in one configuration:
3539
the token at `north_http_server` and `mcp(client)` for the github route
3640
re-stamps it on the outbound request. The everything and time routes have no
3741
guard configured, so no Authorization is added on outbound to those upstreams.
38-
- **Auth-driven challenge pass-through**`github-mcp-server` is started with
39-
`--scope-challenge`, so when an inbound token is missing or under-scoped the
40-
upstream's `HTTP 403 + WWW-Authenticate` flows back through the gateway
41-
unchanged. Clients that implement RFC 6750 / MCP OAuth can complete the
42-
flow externally and retry with the new token.
42+
- **Auth-driven challenge pass-through** — when an inbound token is missing or
43+
under-scoped, the GitHub Copilot upstream responds with
44+
`HTTP 401/403 + WWW-Authenticate: Bearer realm="..." scope="..." error="..."`,
45+
and Zilla converts the response into a `RESET + McpResetEx.bearer` on the
46+
MCP application stream. The proxy and `mcp(server)` re-render that as the
47+
same `HTTP 4xx + WWW-Authenticate` back to the inbound client, so RFC 6750
48+
/ MCP OAuth clients can complete the flow externally and retry with the
49+
new token.
4350

4451
## Requirements
4552

4653
- docker compose
47-
- optional: a GitHub Personal Access Token to exercise the `github` toolkit route
54+
- outbound network access to `api.githubcopilot.com:443`
55+
- optional: a [GitHub Copilot API token](https://docs.github.com/en/copilot)
56+
to exercise the `github` toolkit route end-to-end
4857

4958
## Setup
5059

5160
```bash
5261
docker compose up -d
5362
```
5463

55-
This starts Zilla plus two reachable upstream MCP servers: a Node `everything`
56-
reference server on `:3001` and a Python `time` server on `:3002` wrapped by
57-
`mcp-proxy` for the stdio→HTTP bridge.
58-
59-
To also start the official `github/github-mcp-server` upstream in HTTP mode:
60-
61-
```bash
62-
docker compose --profile github up -d
63-
```
64+
This starts Zilla plus two locally-reachable upstream MCP servers: a Node
65+
`everything` reference server on `:3001` and a Python `time` server on `:3002`
66+
wrapped by `mcp-proxy` for the stdio→HTTP bridge. The `github` route is wired
67+
to GitHub Copilot's public MCP endpoint at `https://api.githubcopilot.com/mcp/`
68+
— no local container is needed.
6469

6570
## Verify
6671

@@ -104,15 +109,10 @@ the elicitation message and reply via `elicitation/result`).
104109

105110
### Call a GitHub tool (bearer flows from client through to upstream)
106111

107-
First start the github upstream:
108-
109-
```bash
110-
docker compose --profile github up -d
111-
```
112-
113-
Issue a github tool call without an `Authorization` header — `github-mcp-server`
114-
returns `HTTP 403` with a `WWW-Authenticate` challenge that propagates back
115-
through the proxy:
112+
Issue a github tool call without an `Authorization` header. Zilla forwards the
113+
unauthenticated call to `api.githubcopilot.com/mcp/`, which responds with an
114+
`HTTP 401` and a `WWW-Authenticate: Bearer ...` challenge. Zilla renders the
115+
challenge back to the inbound client:
116116

117117
```bash
118118
curl -i -N http://localhost:7114/mcp \
@@ -121,16 +121,15 @@ curl -i -N http://localhost:7114/mcp \
121121
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"github/get_me"}}'
122122
```
123123

124-
Mint a [GitHub Personal Access Token](https://github.com/settings/tokens),
125-
then retry with `Authorization: Bearer <PAT>`. Zilla's `identity` guard captures
124+
Retry with `Authorization: Bearer <token>`. Zilla's `identity` guard captures
126125
the bearer at `north_http_server`, and the `mcp(client)` for the github route
127-
re-stamps it on the outbound request — `github-mcp-server` accepts the token
128-
and the tool call completes:
126+
re-stamps it on the outbound request — GitHub Copilot accepts the token and
127+
the tool call completes:
129128

130129
```bash
131-
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...
130+
export GITHUB_COPILOT_TOKEN=...
132131
curl -N http://localhost:7114/mcp \
133-
-H "Authorization: Bearer $GITHUB_PERSONAL_ACCESS_TOKEN" \
132+
-H "Authorization: Bearer $GITHUB_COPILOT_TOKEN" \
134133
-H "Content-Type: application/json" \
135134
-H "Accept: application/json, text/event-stream" \
136135
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"github/get_me"}}'
@@ -154,12 +153,12 @@ memory.
154153
## Teardown
155154

156155
```bash
157-
docker compose --profile github down -v
156+
docker compose down -v
158157
```
159158

160159
## References
161160

162161
- [Zilla docs — `binding-mcp`](https://docs.aklivity.io/zilla/latest/reference/config/bindings/binding-mcp.html)
163162
- [MCP — Streamable HTTP transport](https://modelcontextprotocol.io/docs/concepts/transports)
164163
- [MCP — elicitation](https://modelcontextprotocol.io/specification/draft/client/elicitation)
165-
- [`github/github-mcp-server`](https://github.com/github/github-mcp-server)
164+
- [GitHub Copilot MCP API](https://docs.github.com/en/copilot)

examples/mcp.proxy/compose.yaml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,13 @@ services:
2929
PORT: "3001"
3030

3131
time:
32-
image: ghcr.io/sparfenyuk/mcp-proxy:latest
32+
image: ghcr.io/astral-sh/uv:python3.13-bookworm-slim
3333
hostname: time
3434
restart: unless-stopped
3535
command: >
36-
--port 3002 --host 0.0.0.0 --pass-environment --
36+
uvx mcp-proxy --port 3002 --host 0.0.0.0 --pass-environment --
3737
uvx mcp-server-time
3838
39-
github:
40-
image: ghcr.io/github/github-mcp-server:latest
41-
hostname: github
42-
restart: unless-stopped
43-
command: ["http", "--port=3003", "--scope-challenge"]
44-
profiles:
45-
- github
46-
4739
networks:
4840
default:
4941
driver: bridge

examples/mcp.proxy/etc/zilla.yaml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,24 @@ bindings:
8989
authorization:
9090
name: passthrough
9191
routes:
92-
- exit: south_http_client
92+
- exit: south_http_client_github
9393
with:
9494
headers:
95-
:scheme: http
96-
:authority: github:3003
97-
:path: /mcp
95+
:scheme: https
96+
:authority: api.githubcopilot.com
97+
:path: /mcp/
9898
south_http_client:
9999
type: http
100100
kind: client
101101
exit: south_tcp_client
102+
south_http_client_github:
103+
type: http
104+
kind: client
105+
exit: south_tls_client_github
106+
south_tls_client_github:
107+
type: tls
108+
kind: client
109+
exit: south_tcp_client
102110
south_tcp_client:
103111
type: tcp
104112
kind: client

0 commit comments

Comments
 (0)