Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
09fd6ba
add avatar resource domain
tommaso-moro Jan 7, 2026
c8e646b
add postmessage logic and richer UI
tommaso-moro Jan 7, 2026
769120a
add create issue ui
tommaso-moro Jan 15, 2026
be0d0c2
update ui for issue creatioon
tommaso-moro Jan 15, 2026
73b3622
fix
tommaso-moro Jan 15, 2026
d44f445
ignore banner
tommaso-moro Jan 15, 2026
1ecc2f2
update docs after rebase
mattdholloway Feb 2, 2026
b42185c
update toolsnap for get_me
mattdholloway Feb 2, 2026
a485335
new UI changes
mattdholloway Feb 2, 2026
5f63a9a
update docs
mattdholloway Feb 2, 2026
1a2fb5d
update workflows that need ui build
mattdholloway Feb 2, 2026
0adc140
add UI diff
mattdholloway Feb 2, 2026
043a71d
fix build ui step for windows runners to use git bash
mattdholloway Feb 2, 2026
2398ed0
fix UI diff
mattdholloway Feb 2, 2026
9213bc6
adding trailing slash to uploads url (#1947)
tonytrg Feb 3, 2026
77528c2
refactor issue creation UI
mattdholloway Feb 3, 2026
94aebdd
add AvatarWithFallback component and update UserCard to use it; enhan…
mattdholloway Feb 3, 2026
1868857
fix formatting of button labels
mattdholloway Feb 3, 2026
5b81c2e
add create pull request functionality with UI support and insiders
mattdholloway Feb 3, 2026
c1247ba
update docs
mattdholloway Feb 3, 2026
8aa3269
add test for insiders mode handling in ServerTool schema
mattdholloway Feb 3, 2026
9916243
remove `show_ui` param for now
mattdholloway Feb 4, 2026
cb55964
make insiders mode metadata stripping generic
mattdholloway Feb 4, 2026
6a27ad2
remove ui diff
mattdholloway Feb 4, 2026
41c78db
fix CI
mattdholloway Feb 4, 2026
990d31a
remove redundant mention of old app name
mattdholloway Feb 4, 2026
fd2df91
add node types to fix ide issues for ts code
mattdholloway Feb 4, 2026
5a77e1e
remove unused TriangleDownIcon import
mattdholloway Feb 4, 2026
a9e769b
update @primer/behaviors and electron-to-chromium versions in package…
mattdholloway Feb 4, 2026
1805161
add check to ensure base and head are not the same when creating a ne…
mattdholloway Feb 4, 2026
391651b
remove old show_ui
mattdholloway Feb 4, 2026
9abaabc
fix gitignore for dist so builds dont break
mattdholloway Feb 4, 2026
45aca5e
add tests for insiders mode handling and metadata stripping in Server…
mattdholloway Feb 4, 2026
031f791
remove unused state and components from CreatePRApp
mattdholloway Feb 4, 2026
44ffaf7
fix ui build
mattdholloway Feb 4, 2026
f71d912
update docker build to fix npm issue
mattdholloway Feb 4, 2026
c716d88
remove reference to show_ui
mattdholloway Feb 4, 2026
ee5ca8e
fix GetFlags calls and server.go for http-stack-2 compatibility
mattdholloway Feb 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/code-scanning.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,18 @@ jobs:
go-version: ${{ fromJSON(steps.resolve-environment.outputs.environment).configuration.go.version }}
cache: false

- name: Set up Node.js
if: matrix.language == 'go'
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json

- name: Build UI
if: matrix.language == 'go'
run: script/build-ui

- name: Autobuild
uses: github/codeql-action/autobuild@v4

Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/docs-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ jobs:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json

- name: Build UI
run: script/build-ui

- name: Set up Go
uses: actions/setup-go@v6
with:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ jobs:
- name: Check out code
uses: actions/checkout@v6

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json

- name: Build UI
shell: bash
run: script/build-ui

- name: Set up Go
uses: actions/setup-go@v6
with:
Expand All @@ -34,6 +45,7 @@ jobs:
run: go mod tidy -diff

- name: Run unit tests
shell: bash
run: script/test

- name: Build
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ jobs:
- name: Check out code
uses: actions/checkout@v6

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json

- name: Build UI
run: script/build-ui

- name: Set up Go
uses: actions/setup-go@v6
with:
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/license-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: gh pr checkout ${{ github.event.pull_request.number }}

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json

- name: Build UI
run: script/build-ui

- name: Set up Go
uses: actions/setup-go@v6
with:
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: ui/package-lock.json
- name: Build UI
run: script/build-ui
- uses: actions/setup-go@v6
with:
go-version: stable
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/mcp-diff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ jobs:
with:
fetch-depth: 0

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Build UI
run: script/build-ui

- name: Run MCP Server Diff
uses: SamMorrowDrums/mcp-server-diff@v2.3.5
with:
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ e2e.test

.history
conformance-report/

# UI build artifacts
ui/dist/
ui/node_modules/

# Embedded UI assets (built from ui/)
pkg/github/ui_dist/*
!pkg/github/ui_dist/.gitkeep
!pkg/github/ui_dist/.placeholder.html
17 changes: 15 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
FROM node:20-alpine AS ui-build
WORKDIR /app
COPY ui/package*.json ./ui/
RUN cd ui && npm ci
COPY ui/ ./ui/
# Create output directory and build - vite outputs directly to pkg/github/ui_dist/
RUN mkdir -p ./pkg/github/ui_dist && \
cd ui && npm run build

FROM golang:1.25.6-alpine AS build
ARG VERSION="dev"

Expand All @@ -8,11 +17,15 @@ WORKDIR /build
RUN --mount=type=cache,target=/var/cache/apk \
apk add git

# Copy source code (including ui_dist placeholder)
COPY . .

# Copy built UI assets over the placeholder
COPY --from=ui-build /app/pkg/github/ui_dist/* ./pkg/github/ui_dist/

# Build the server
# go build automatically download required module dependencies to /go/pkg/mod
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
--mount=type=bind,target=. \
CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=${VERSION} -X main.commit=$(git rev-parse HEAD) -X main.date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
-o /bin/github-mcp-server ./cmd/github-mcp-server

Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,11 @@ The following sets of tools are available:
- `title`: Issue title (string, optional)
- `type`: Type of this issue. Only use if the repository has issue types configured. Use list_issue_types tool to get valid type values for the organization. If the repository doesn't support issue types, omit this parameter. (string, optional)

- **list_assignees** - List assignable users
- **Required OAuth Scopes**: `repo`
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)

- **list_issue_types** - List available issue types
- **Required OAuth Scopes**: `read:org`
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `write:org`
Expand All @@ -860,6 +865,12 @@ The following sets of tools are available:
- `since`: Filter by date (ISO 8601 timestamp) (string, optional)
- `state`: Filter by state, by default both open and closed issues are returned when not provided (string, optional)

- **list_milestones** - List milestones
- **Required OAuth Scopes**: `repo`
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- `state`: Filter by state (open, closed, all). Default: open (string, optional)

- **search_issues** - Search issues
- **Required OAuth Scopes**: `repo`
- `order`: Sort order (string, optional)
Expand Down Expand Up @@ -1035,14 +1046,14 @@ The following sets of tools are available:

- **create_pull_request** - Open new pull request
- **Required OAuth Scopes**: `repo`
- `base`: Branch to merge into (string, required)
- `base`: Branch to merge into (string, optional)
- `body`: PR description (string, optional)
- `draft`: Create as draft PR (boolean, optional)
- `head`: Branch containing changes (string, required)
- `head`: Branch containing changes (string, optional)
- `maintainer_can_modify`: Allow maintainer edits (boolean, optional)
- `owner`: Repository owner (string, required)
- `repo`: Repository name (string, required)
- `title`: PR title (string, required)
- `title`: PR title (string, optional)

- **list_pull_requests** - List pull requests
- **Required OAuth Scopes**: `repo`
Expand Down
5 changes: 5 additions & 0 deletions internal/ghmcp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,11 @@ func NewStdioMCPServer(ctx context.Context, cfg github.MCPServerConfig) (*mcp.Se
return nil, fmt.Errorf("failed to create GitHub MCP server: %w", err)
}

// Register MCP App UI resources (static resources for tool UI) - insiders only
if cfg.InsidersMode {
github.RegisterUIResources(ghServer)
}

ghServer.AddReceivingMiddleware(addUserAgentsMiddleware(cfg, clients.rest, clients.gqlHTTP))

return ghServer, nil
Expand Down
14 changes: 10 additions & 4 deletions pkg/github/__toolsnaps__/create_pull_request.snap
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
{
"_meta": {
"ui": {
"resourceUri": "ui://github-mcp-server/pr-write",
"visibility": [
"model",
"app"
]
}
},
"annotations": {
"title": "Open new pull request"
},
Expand Down Expand Up @@ -40,10 +49,7 @@
},
"required": [
"owner",
"repo",
"title",
"head",
"base"
"repo"
],
"type": "object"
},
Expand Down
5 changes: 5 additions & 0 deletions pkg/github/__toolsnaps__/get_me.snap
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
{
"_meta": {
"ui": {
"resourceUri": "ui://github-mcp-server/get-me"
}
},
"annotations": {
"readOnlyHint": true,
"title": "Get my user profile"
Expand Down
9 changes: 9 additions & 0 deletions pkg/github/__toolsnaps__/issue_write.snap
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
{
"_meta": {
"ui": {
"resourceUri": "ui://github-mcp-server/issue-write",
"visibility": [
"model",
"app"
]
}
},
"annotations": {
"title": "Create or update issue."
},
Expand Down
25 changes: 25 additions & 0 deletions pkg/github/__toolsnaps__/list_assignees.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"annotations": {
"readOnlyHint": true,
"title": "List assignable users"
},
"description": "List available assignees for a repository. Returns users who can be assigned to issues.",
"inputSchema": {
"properties": {
"owner": {
"description": "Repository owner",
"type": "string"
},
"repo": {
"description": "Repository name",
"type": "string"
}
},
"required": [
"owner",
"repo"
],
"type": "object"
},
"name": "list_assignees"
}
34 changes: 34 additions & 0 deletions pkg/github/__toolsnaps__/list_milestones.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"annotations": {
"readOnlyHint": true,
"title": "List milestones"
},
"description": "List milestones for a repository.",
"inputSchema": {
"properties": {
"owner": {
"description": "Repository owner",
"type": "string"
},
"repo": {
"description": "Repository name",
"type": "string"
},
"state": {
"description": "Filter by state (open, closed, all). Default: open",
"enum": [
"open",
"closed",
"all"
],
"type": "string"
}
},
"required": [
"owner",
"repo"
],
"type": "object"
},
"name": "list_milestones"
}
8 changes: 8 additions & 0 deletions pkg/github/context_tools.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import (
"github.com/shurcooL/githubv4"
)

// GetMeUIResourceURI is the URI for the get_me tool's MCP App UI resource.
const GetMeUIResourceURI = "ui://github-mcp-server/get-me"

// UserDetails contains additional fields about a GitHub user not already
// present in MinimalUser. Used by get_me context tool but omitted from search_users.
type UserDetails struct {
Expand Down Expand Up @@ -51,6 +54,11 @@ func GetMe(t translations.TranslationHelperFunc) inventory.ServerTool {
// Use json.RawMessage to ensure "properties" is included even when empty.
// OpenAI strict mode requires the properties field to be present.
InputSchema: json.RawMessage(`{"type":"object","properties":{}}`),
Meta: mcp.Meta{
"ui": map[string]any{
"resourceUri": GetMeUIResourceURI,
},
},
},
nil,
func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, _ map[string]any) (*mcp.CallToolResult, any, error) {
Expand Down
Loading