@@ -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
2226The 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
5261docker 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
118118curl -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
126125the 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= ...
132131curl -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 )
0 commit comments