A Swift-based local server for macOS that bridges GitHub Copilot with Xcode's Code Intelligence. It acts as an OpenAI-compatible proxy, translating Xcode's requests into GitHub Copilot API calls.
No API keys to manage, no third-party accounts — just your GitHub Copilot subscription.
Xcode ──► Local Server (localhost:8080) ──► GitHub Copilot API
┌──────────────────────────────┐
│ • GitHub device code OAuth │
│ • Manages Copilot tokens │
│ • Streams SSE responses │
│ • Optional MCP agent loop │
└──────────────────────────────┘
The server exposes the following OpenAI-compatible endpoints that Xcode connects to:
GET /health— Returns server health status, uptime, and MCP bridge statusGET /v1/models— Lists available Copilot modelsPOST /v1/chat/completions— Handles chat completions with streaming SSE
For models that only support the Responses API (e.g. Codex models), the server automatically detects this via the model's supported endpoints and internally translates chat completion requests into Responses API calls. The response is then adapted back into the chat completions SSE format, so Xcode always communicates using the same /v1/chat/completions endpoint.
The server uses a multi-layered authentication strategy:
- Stored OAuth token — On first use, a GitHub Device Code OAuth flow is triggered. The resulting token is stored at
~/.config/xcode-assistant-copilot-server/github-token.json(with0600permissions) and reused on subsequent launches. - GitHub CLI fallback — If no stored token is found, the server tries
gh auth tokenfrom the GitHub CLI as a fallback. - Automatic device code flow — If the Copilot token exchange fails (e.g. the
ghtoken lacks Copilot scopes), the server automatically initiates a device code flow. You'll be prompted to visit a URL and enter a code in your browser.
The device code flow uses the same OAuth client ID (Iv1.b507a08c87ecfe98) as other Copilot integrations (copilot.vim, copilot.el, etc.) to ensure the resulting token has access to the Copilot API.
Once authenticated, the server exchanges your GitHub token for a short-lived Copilot JWT, caches it in memory, and automatically refreshes it before expiry.
- macOS 26 or newer
- Swift 6.2.3+ (install via Swiftly)
- GitHub Copilot subscription — Individual, Business, or Enterprise
- Xcode 26 or newer (Xcode 26.3+ for MCP tool support)
- GitHub CLI (
gh) — optional, used as a fallback authentication method
brew install mobile-ar/xcode-assistant-copilot-server/xcode-assistant-copilot-serveror
brew tap mobile-ar/xcode-assistant-copilot-server
brew install xcode-assistant-copilot-servergit clone https://github.com/user/xcode-assistant-copilot-server.git
cd xcode-assistant-copilot-server
swift build -c release
sudo cp .build/release/xcode-assistant-copilot-server /usr/local/bin/source ~/.zshrcor exec your Shell
exec zshor re-start your terminal if none of the avobe works.
xcode-assistant-copilot-serverThe server starts on http://127.0.0.1:8080 by default.
On the first run, if no stored OAuth token is found, the server will prompt you to authenticate via the GitHub device code flow:
[INFO] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[INFO] GitHub authentication required.
[INFO] Please visit: https://github.com/login/device
[INFO] and enter code: ABCD-1234
[INFO] ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Open the URL, enter the code, and authorize the application. The token is stored for future use.
If you prefer to authenticate via the GitHub CLI instead of the device code flow:
brew install gh
gh auth login- Open Xcode → Settings → Intelligence
- Click Add a provider
- Select Locally hosted
- Set the port to
8080(or whichever port you configured) - Give it a description (e.g. "Copilot")
- Click Add
Under the provider's Advanced settings in Xcode:
- Enable Allow tools to let Copilot use tool calling
- Enable Xcode Tools under MCP (requires Xcode 26.3+) for MCP agent capabilities
| Option | Default | Description |
|---|---|---|
--port <number> |
8080 |
Port to listen on (1–65535) |
--log-level <level> |
info |
Log verbosity: none, error, warning, info, debug, all |
--config <path> |
— | Path to a JSON configuration file |
--version |
— | Show the version. |
-h, --help |
— | Show help information. |
Run on a custom port with debug logging:
xcode-assistant-copilot-server --port 9090 --log-level debugRun with a custom configuration file:
xcode-assistant-copilot-server --config ./config.jsonThe server can be configured via a JSON file passed with the --config flag. If no config file is provided, sensible defaults are used.
{
"mcpServers": {
"xcode": {
"type": "local",
"command": "xcrun",
"args": ["mcpbridge"],
"allowedTools": ["*"]
}
},
"allowedCliTools": [],
"bodyLimitMiB": 4,
"excludedFilePatterns": [],
"reasoningEffort": "xhigh",
"autoApprovePermissions": ["read", "mcp"]
}A dictionary of MCP (Model Context Protocol) server configurations. Each entry defines an MCP server that the agent loop can use for tool execution.
| Field | Type | Description |
|---|---|---|
type |
string |
Server type: local, stdio, http, or sse |
command |
string |
Command to spawn (for local/stdio types) |
args |
[string] |
Arguments for the command |
env |
{string: string} |
Environment variables |
cwd |
string |
Working directory |
url |
string |
URL (for http/sse types) |
headers |
{string: string} |
HTTP headers (for http/sse types) |
allowedTools |
[string] |
List of allowed tool names, or ["*"] for all |
timeout |
number |
Timeout in seconds |
An array of CLI tool names that Copilot is allowed to invoke. Use ["*"] to allow all CLI tools. Defaults to an empty array (no CLI tools allowed).
Maximum request body size in MiB. Defaults to 4.
An array of file path patterns to exclude from Xcode search results sent to Copilot. Matching code blocks are stripped from the context before forwarding.
Controls the reasoning effort level for Copilot responses. Options: low, medium, high, xhigh. Defaults to xhigh.
The server automatically retries with a lower reasoning effort if the model rejects the configured level, and caches the maximum supported level per model for subsequent requests.
Controls which permission types are automatically approved without prompting. Can be:
- A boolean (
trueto approve all,falseto deny all) - An array of permission kinds:
read,write,shell,mcp,url
Defaults to ["read", "mcp"].
When no MCP servers are configured, the server operates as a transparent streaming proxy:
Xcode → Server → Copilot API
Xcode ← Server ← Copilot API (SSE stream)
Tool calls from Copilot are forwarded directly to Xcode, which handles tool execution and sends results back in subsequent requests.
When MCP servers are configured (e.g. xcrun mcpbridge), the server runs an internal agent loop:
Xcode → Server → Copilot API
↕ (internal tool loop)
MCP Bridge ↔ xcrun mcpbridge
↓
Xcode ← Server (final streamed response)
The server buffers Copilot's response. If tool calls target MCP tools, it executes them internally via the MCP bridge, appends results to the conversation, and re-requests from Copilot. This continues until a final text response is produced, which is then streamed to Xcode.
- Localhost only — The server binds exclusively to
127.0.0.1and is not accessible from other machines on the network. - User-Agent filtering — Only requests with a
Xcode/user-agent are accepted. All other requests are rejected (except the/healthendpoint, which is exempt from this check). - CORS middleware — The server includes CORS headers (
Access-Control-Allow-Origin: *) to handle preflightOPTIONSrequests. - Secure token storage — The OAuth token from the device code flow is stored at
~/.config/xcode-assistant-copilot-server/github-token.jsonwith0600permissions (owner read/write only). - In-memory Copilot tokens — Short-lived Copilot JWT tokens are cached in memory only and automatically refreshed before expiry. They are never written to disk.
Sources/
XcodeAssistantCopilotServer/ # Library target
Configuration/ # Config model and loader
Handlers/ # HTTP route handlers (health, models, chat completions)
Models/ # Request/response models, MCP messages, OAuth tokens
Networking/ # HTTP client, endpoint protocol, request headers
Endpoints/ # Concrete endpoint definitions (Copilot API, device flow, etc.)
Server/ # Hummingbird server, route registry, middleware (CORS, logging, user-agent)
Services/ # Auth, Copilot API, MCP bridge, device flow, SSE parser, signal handler
Utilities/ # Logger, prompt formatter, error response builder, extensions
xcode-assistant-copilot-server/ # Executable target
App.swift # CLI entry point (ArgumentParser)
Tests/
XcodeAssistantCopilotServerTests/ # Unit tests
The device code flow requires an internet connection to reach github.com. Make sure you can access https://github.com/login/device in your browser.
This means authentication succeeded but your GitHub account does not have an active Copilot subscription. Verify your subscription at github.com/settings/copilot.
If you previously authenticated but the token has been revoked or expired, delete the stored token and restart the server:
rm ~/.config/xcode-assistant-copilot-server/github-token.json
xcode-assistant-copilot-serverThe server will trigger a fresh device code flow.
This is not an error — it just means gh is not installed. The server will use the device code flow instead. If you want to suppress this warning, install the GitHub CLI:
brew install gh
gh auth login- Confirm the port matches between the server and Xcode settings.
- Make sure Xcode's Intelligence provider is set to Locally hosted.
- Check that no firewall is blocking localhost connections.
- Try running with
--log-level debugfor more details.
- MCP support requires Xcode 26.3 or newer.
- Make sure
xcrun mcpbridgeis available by running it manually in the terminal. - The server will continue without MCP support if the bridge fails to start.
If a model doesn't support the configured reasoning effort level, the server automatically retries with progressively lower levels (xhigh → high → medium → low). The maximum supported level is cached per model to avoid repeated retries. No action is needed — this is handled transparently.
See the LICENSE file for details.