Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2f1b6e3
feat(resources): add CodeQL MaD extensions support
data-douser Apr 23, 2026
e1287a3
Sync server/dist/**
data-douser Apr 24, 2026
0c68c46
Register MaD library-modeling resources for rust and swift; address r…
Copilot Apr 24, 2026
228b68f
Merge branch 'main' into dd/mad-ql/1
data-douser Apr 24, 2026
cffb3f8
Build(deps): bump actions/setup-go from 5.6.0 to 6.4.0 (#265)
dependabot[bot] Apr 24, 2026
b80df0d
Update MaD tuple format in overview resource
data-douser Apr 24, 2026
db62263
Fix invalid JSON Schema for `query_results_cache_retrieve` (#263)
Copilot Apr 24, 2026
8a63678
Build(deps): bump actions/setup-node from 6.3.0 to 6.4.0 (#264)
dependabot[bot] Apr 24, 2026
d74ee0f
Update MaD tuple format in overview resource
data-douser Apr 24, 2026
46fdc62
Merge branch 'dd/mad-ql/1' of github.com:advanced-security/codeql-dev…
data-douser Apr 24, 2026
4da5417
feat(resources): add CodeQL MaD extensions support
data-douser Apr 23, 2026
9787e0a
Sync server/dist/**
data-douser Apr 24, 2026
b17d0f6
Register MaD library-modeling resources for rust and swift; address r…
Copilot Apr 24, 2026
4a69c81
Update MaD tuple format in overview resource
data-douser Apr 24, 2026
93ab431
Rebuild server/dist/codeql-development-mcp-server.js.map
data-douser Apr 24, 2026
b573add
Merge branch 'dd/mad-ql/1' of github.com:advanced-security/codeql-dev…
data-douser Apr 24, 2026
0a37154
wire data-extension-development prompt and fix type errors
data-douser Apr 27, 2026
c1a86b2
Address review feedback for PR #266
data-douser May 1, 2026
2a73ba4
Fix client/ go lint & format
data-douser May 1, 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
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Setup Go environment
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
cache-dependency-path: 'client/go.sum'
go-version-file: 'client/go.mod'
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Setup Go environment
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
cache-dependency-path: 'client/go.sum'
go-version-file: 'client/go.mod'
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/lint-and-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
node-version-file: '.node-version'

- name: Lint and Format - Setup Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
with:
go-version-file: 'client/go.mod'
cache-dependency-path: 'client/go.sum'
Expand Down
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,28 @@ release cadence.

_Changes on `main` since the latest tagged release that have not yet been included in a stable release._

### Added

#### MCP Server Prompts

| Prompt | Description |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `data_extension_development` | End-to-end workflow for authoring CodeQL data extensions (Models-as-Data) for third-party libraries; restricts `language` to MaD-supported languages. ([#266](https://github.com/advanced-security/codeql-development-mcp-server/pull/266)) |

#### MCP Server Resources

| URI | Description |
| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `codeql://learning/data-extensions` | Models-as-Data (MaD) overview: YAML model formats, extensible predicates, and model-pack layout. ([#266](https://github.com/advanced-security/codeql-development-mcp-server/pull/266)) |
| `codeql://languages/rust/library-modeling` | Rust-specific library-modeling guide (crate-path-based MaD format) for the `data_extension_development` workflow. ([#266](https://github.com/advanced-security/codeql-development-mcp-server/pull/266)) |
| `codeql://languages/swift/library-modeling` | Swift-specific library-modeling guide (MaD tuple format) for the `data_extension_development` workflow. ([#266](https://github.com/advanced-security/codeql-development-mcp-server/pull/266)) |

Every CodeQL language that supports Models-as-Data upstream (`cpp`, `csharp`, `go`, `java`, `javascript`, `python`, `ruby`, `rust`, `swift`) now has a registered `codeql://languages/<language>/library-modeling` resource. `actions` is intentionally excluded because it does not support data extensions.

### Fixed

- **`query_results_cache_retrieve` rejected by GitHub Copilot Chat (HTTP 400 invalid schema)** — The `lineRange` and `resultIndices` parameters were defined with `z.tuple([...])`, which the MCP SDK serialized to a bare-array JSON Schema value (e.g. `[{"type":"integer"}, {"type":"integer"}]`). GitHub Copilot Chat enforces strict JSON Schema validation and rejected the entire `ql-mcp` server with `"... is not of type 'object', 'boolean'"`. Both parameters now use `z.object({ start, end })` so they serialize to a valid `type: "object"` JSON Schema. Tool callers must now pass `{ "lineRange": { "start": 1, "end": 10 } }` instead of `{ "lineRange": [1, 10] }`. ([#263](https://github.com/advanced-security/codeql-development-mcp-server/pull/263))

Comment thread
data-douser marked this conversation as resolved.
## [v2.25.2] — 2026-04-15

### Highlights
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/code_scanning_download_analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,6 @@ func runDownloadAnalysis(cmd *cobra.Command, _ []string) error {
}
}

fmt.Fprintf(cmd.OutOrStdout(), "Downloaded SARIF to %s (%d bytes)\n", outPath, len(sarif))
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "Downloaded SARIF to %s (%d bytes)\n", outPath, len(sarif))
return nil
}
4 changes: 2 additions & 2 deletions client/cmd/code_scanning_list_alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,11 @@ func runListAlerts(cmd *cobra.Command, _ []string) error {
}

w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 4, 2, ' ', 0)
fmt.Fprintln(w, "NUM\tSTATE\tRULE\tSEVERITY\tFILE:LINE\tCREATED")
_, _ = fmt.Fprintln(w, "NUM\tSTATE\tRULE\tSEVERITY\tFILE:LINE\tCREATED")
for _, a := range alerts {
loc := a.MostRecentInstance.Location
locStr := fmt.Sprintf("%s:%d", loc.Path, loc.StartLine)
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\n",
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%s\t%s\n",
a.Number, a.State, a.Rule.ID, a.Rule.Severity, locStr, a.CreatedAt)
}
return w.Flush()
Expand Down
4 changes: 2 additions & 2 deletions client/cmd/code_scanning_list_analyses.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ func runListAnalyses(cmd *cobra.Command, _ []string) error {
}

w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 4, 2, ' ', 0)
fmt.Fprintln(w, "ID\tTOOL\tREF\tCATEGORY\tRESULTS\tRULES\tCREATED")
_, _ = fmt.Fprintln(w, "ID\tTOOL\tREF\tCATEGORY\tRESULTS\tRULES\tCREATED")
for _, a := range analyses {
fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\t%d\t%s\n",
_, _ = fmt.Fprintf(w, "%d\t%s\t%s\t%s\t%d\t%d\t%s\n",
a.ID, a.Tool.Name, a.Ref, a.Category, a.ResultsCount, a.RulesCount, a.CreatedAt)
}
return w.Flush()
Expand Down
2 changes: 1 addition & 1 deletion client/cmd/integration_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func runIntegrationTests(cmd *cobra.Command, _ []string) error {
// server/.tmp/) which causes log directory validation failures.
tmpBase := filepath.Join(repoRoot, ".tmp")
if os.Getenv("CODEQL_MCP_TMP_DIR") == "" {
os.Setenv("CODEQL_MCP_TMP_DIR", tmpBase)
_ = os.Setenv("CODEQL_MCP_TMP_DIR", tmpBase)
}

// Connect to MCP server
Expand Down
24 changes: 12 additions & 12 deletions client/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func runListTools(_ *cobra.Command, _ []string) error {
if err != nil {
return err
}
defer client.Close()
defer func() { _ = client.Close() }()

tools, err := client.ListTools(ctx)
if err != nil {
Expand All @@ -87,15 +87,15 @@ func runListTools(_ *cobra.Command, _ []string) error {
}

w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
fmt.Fprintf(w, "NAME\tDESCRIPTION\n")
_, _ = fmt.Fprintf(w, "NAME\tDESCRIPTION\n")
for _, t := range tools {
desc := t.Description
if len(desc) > 80 {
desc = desc[:77] + "..."
}
fmt.Fprintf(w, "%s\t%s\n", t.Name, desc)
_, _ = fmt.Fprintf(w, "%s\t%s\n", t.Name, desc)
}
w.Flush()
_ = w.Flush()
fmt.Printf("\n%d tools registered\n", len(tools))
return nil
}
Expand All @@ -106,7 +106,7 @@ func runListPrompts(_ *cobra.Command, _ []string) error {
if err != nil {
return err
}
defer client.Close()
defer func() { _ = client.Close() }()

prompts, err := client.ListPrompts(ctx)
if err != nil {
Expand All @@ -132,15 +132,15 @@ func runListPrompts(_ *cobra.Command, _ []string) error {
}

w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
fmt.Fprintf(w, "NAME\tDESCRIPTION\n")
_, _ = fmt.Fprintf(w, "NAME\tDESCRIPTION\n")
for _, p := range prompts {
desc := p.Description
if len(desc) > 80 {
desc = desc[:77] + "..."
}
fmt.Fprintf(w, "%s\t%s\n", p.Name, desc)
_, _ = fmt.Fprintf(w, "%s\t%s\n", p.Name, desc)
}
w.Flush()
_ = w.Flush()
fmt.Printf("\n%d prompts registered\n", len(prompts))
return nil
}
Expand All @@ -151,7 +151,7 @@ func runListResources(_ *cobra.Command, _ []string) error {
if err != nil {
return err
}
defer client.Close()
defer func() { _ = client.Close() }()

resources, err := client.ListResources(ctx)
if err != nil {
Expand All @@ -178,15 +178,15 @@ func runListResources(_ *cobra.Command, _ []string) error {
}

w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
fmt.Fprintf(w, "NAME\tURI\tDESCRIPTION\n")
_, _ = fmt.Fprintf(w, "NAME\tURI\tDESCRIPTION\n")
for _, r := range resources {
desc := r.Description
if len(desc) > 60 {
desc = desc[:57] + "..."
}
fmt.Fprintf(w, "%s\t%s\t%s\n", r.Name, r.URI, desc)
_, _ = fmt.Fprintf(w, "%s\t%s\t%s\n", r.Name, r.URI, desc)
}
w.Flush()
_ = w.Flush()
fmt.Printf("\n%d resources registered\n", len(resources))
return nil
}
8 changes: 4 additions & 4 deletions client/cmd/use_prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func runUsePrompt(_ *cobra.Command, args []string) error {
if err != nil {
return err
}
defer client.Close()
defer func() { _ = client.Close() }()

result, err := mcpclient.GetPrompt(ctx, client, promptName, params)
if err != nil {
Expand All @@ -58,11 +58,11 @@ func outputPromptMessages(result *mcpclient.PromptMessages) error {
if err != nil {
return err
}
fmt.Fprintln(os.Stdout, s)
_, _ = fmt.Fprintln(os.Stdout, s)
case "markdown":
fmt.Fprint(os.Stdout, mcpclient.FormatPromptMessagesMarkdown(result))
_, _ = fmt.Fprint(os.Stdout, mcpclient.FormatPromptMessagesMarkdown(result))
default:
fmt.Fprint(os.Stdout, mcpclient.FormatPromptMessagesText(result))
_, _ = fmt.Fprint(os.Stdout, mcpclient.FormatPromptMessagesText(result))
}
return nil
}
8 changes: 4 additions & 4 deletions client/cmd/use_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func runUseResource(_ *cobra.Command, args []string) error {
if err != nil {
return err
}
defer client.Close()
defer func() { _ = client.Close() }()

result, err := mcpclient.ReadResource(ctx, client, uri)
if err != nil {
Expand All @@ -50,11 +50,11 @@ func outputResourceContent(result *mcpclient.ResourceContent) error {
if err != nil {
return err
}
fmt.Fprintln(os.Stdout, s)
_, _ = fmt.Fprintln(os.Stdout, s)
case "markdown":
fmt.Fprint(os.Stdout, mcpclient.FormatResourceContentMarkdown(result))
_, _ = fmt.Fprint(os.Stdout, mcpclient.FormatResourceContentMarkdown(result))
default:
fmt.Fprint(os.Stdout, mcpclient.FormatResourceContentText(result))
_, _ = fmt.Fprint(os.Stdout, mcpclient.FormatResourceContentText(result))
}
return nil
}
8 changes: 4 additions & 4 deletions client/cmd/use_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func runUseTool(_ *cobra.Command, args []string) error {
if err != nil {
return err
}
defer client.Close()
defer func() { _ = client.Close() }()

result, err := mcpclient.CallTool(ctx, client, toolName, params)
if err != nil {
Expand All @@ -59,11 +59,11 @@ func outputToolResult(result *mcpclient.ToolResult) error {
if err != nil {
return err
}
fmt.Fprintln(os.Stdout, s)
_, _ = fmt.Fprintln(os.Stdout, s)
case "markdown":
fmt.Fprint(os.Stdout, mcpclient.FormatToolResultMarkdown(result))
_, _ = fmt.Fprint(os.Stdout, mcpclient.FormatToolResultMarkdown(result))
default:
fmt.Fprint(os.Stdout, mcpclient.FormatToolResultText(result))
_, _ = fmt.Fprint(os.Stdout, mcpclient.FormatToolResultText(result))
}
if result.IsError {
return fmt.Errorf("tool returned error")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"toolName": "query_results_cache_retrieve",
"parameters": {
"cacheKey": "nonexistent-key-for-test",
"maxLines": 50
"maxLines": 50,
"lineRange": { "start": 1, "end": 10 }
},
"success": true,
"description": "Successfully handled cache retrieve for non-existent key"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"toolName": "query_results_cache_retrieve",
"parameters": {
"cacheKey": "nonexistent-key-for-test",
"maxLines": 50
"maxLines": 50,
"lineRange": { "start": 1, "end": 10 }
},
"expectedSuccess": true,
"description": "Test query_results_cache_retrieve returns appropriate message for missing cache key"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"toolName": "query_results_cache_retrieve",
"arguments": {
"cacheKey": "nonexistent-key-for-test",
"maxLines": 50
"maxLines": 50,
"lineRange": { "start": 1, "end": 10 }
}
}
12 changes: 6 additions & 6 deletions client/internal/mcp/primitives.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,10 @@ func FormatResourceContentText(rc *ResourceContent) string {
sb.WriteString("\n---\n")
}
if item.URI != "" {
sb.WriteString(fmt.Sprintf("URI: %s\n", item.URI))
fmt.Fprintf(&sb, "URI: %s\n", item.URI)
}
if item.MIMEType != "" {
sb.WriteString(fmt.Sprintf("Type: %s\n", item.MIMEType))
fmt.Fprintf(&sb, "Type: %s\n", item.MIMEType)
}
sb.WriteString("\n")
sb.WriteString(item.Text)
Expand All @@ -211,13 +211,13 @@ func FormatResourceContentText(rc *ResourceContent) string {
func FormatPromptMessagesText(pm *PromptMessages) string {
var sb strings.Builder
if pm.Description != "" {
sb.WriteString(fmt.Sprintf("Description: %s\n\n", pm.Description))
fmt.Fprintf(&sb, "Description: %s\n\n", pm.Description)
}
for i, msg := range pm.Messages {
if i > 0 {
sb.WriteString("\n---\n")
}
sb.WriteString(fmt.Sprintf("[%s]\n", msg.Role))
fmt.Fprintf(&sb, "[%s]\n", msg.Role)
sb.WriteString(msg.Content)
sb.WriteString("\n")
}
Expand Down Expand Up @@ -254,13 +254,13 @@ func FormatResourceContentMarkdown(rc *ResourceContent) string {
func FormatPromptMessagesMarkdown(pm *PromptMessages) string {
var sb strings.Builder
if pm.Description != "" {
sb.WriteString(fmt.Sprintf("*%s*\n\n", pm.Description))
fmt.Fprintf(&sb, "*%s*\n\n", pm.Description)
}
for i, msg := range pm.Messages {
if i > 0 {
sb.WriteString("\n---\n\n")
}
sb.WriteString(fmt.Sprintf("### %s\n\n", msg.Role))
fmt.Fprintf(&sb, "### %s\n\n", msg.Role)
sb.WriteString(msg.Content)
sb.WriteString("\n")
}
Expand Down
Loading
Loading