Skip to content

Conversation

@yodagg
Copy link

@yodagg yodagg commented Jan 9, 2026

  • Environment : Self-hosted company GitLab 10.7.3; Trae IDE as MCP client
  • Issue : list_projects/get_project/get_repository_tree worked, but get_file_contents failed with Invalid arguments: Invalid input , blocking reads of files like package.json
  • Root cause :
    • Trae may send path instead of file_path , and/or omit project_id when GITLAB_PROJECT_ID is configured, causing strict input schema validation to reject the call
    • GitLab 10.7.3 file API responses can differ from the strict expected schema, causing response parsing failures
  • Change (schemas only, schemas.ts ):
    • Make GetFileContentsSchema tolerant: accept path alias, allow optional project_id , normalize inputs
    • Relax GitLabFileContentSchema fields to improve compatibility with older/self-hosted GitLab responses

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request aims to fix compatibility issues with the Trae IDE client and GitLab 10.7.3 by making the get_file_contents API more tolerant of different input formats and response schemas.

Changes:

  • Modified GetFileContentsSchema to accept both file_path and path parameters, with optional project_id
  • Made all fields in GitLabFileContentSchema optional except file_path to accommodate older GitLab API versions
  • Added input normalization via transform to handle parameter variations from different MCP clients

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

.transform(data => ({
project_id: (data.project_id ?? "").trim(),
file_path: (data.file_path ?? data.path ?? "").trim(),
ref: data.ref,
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ref field is passed through without trimming, but if it contains only whitespace, this could cause issues. The getFileContents function checks if ref is falsy (line 1446 in index.ts) to determine whether to fetch the default branch. An empty string or whitespace-only string is truthy, so it would be passed to the API as-is, potentially causing errors.

Consider trimming ref and converting empty strings to undefined in the transform, similar to how file_path is handled.

Copilot uses AI. Check for mistakes.
Comment on lines +1061 to +1081
export const GetFileContentsSchema = z
.object({
project_id: z.coerce.string().optional().describe("Project ID or URL-encoded path"),
file_path: z.string().optional().describe("Path to the file or directory"),
path: z.string().optional().describe("Alias of file_path"),
ref: z.string().optional().describe("Branch/tag/commit to get contents from"),
})
.superRefine((data, ctx) => {
if (!data.file_path && !data.path) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Either 'file_path' or 'path' must be provided",
path: ["file_path"],
});
}
})
.transform(data => ({
project_id: (data.project_id ?? "").trim(),
file_path: (data.file_path ?? data.path ?? "").trim(),
ref: data.ref,
}));
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema changes to GetFileContentsSchema introduce significant behavioral changes, but there are no corresponding test cases to validate these changes. The new behavior around optional project_id, path parameter aliasing, and the transform logic should be covered by unit tests to prevent regressions.

Consider adding test cases that validate: 1) behavior when project_id is omitted and GITLAB_PROJECT_ID is set, 2) behavior when path is provided instead of file_path, 3) behavior when both file_path and path are provided, 4) edge cases like whitespace-only values.

Copilot uses AI. Check for mistakes.
}
})
.transform(data => ({
project_id: (data.project_id ?? "").trim(),
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The transform always returns an empty string for project_id when it's not provided, even though the field is optional. This causes an issue when GITLAB_PROJECT_ID environment variable is set. When project_id is not provided by the client, the transform returns an empty string "", which is then passed to getFileContents. This empty string bypasses the fallback logic in getEffectiveProjectId (line 1338 in index.ts) which only falls back to GITLAB_PROJECT_ID when projectId is falsy. An empty string is truthy, so the fallback never happens, causing API errors.

Consider returning undefined instead of an empty string when project_id is not provided, or handling empty strings in getEffectiveProjectId.

Copilot uses AI. Check for mistakes.
Comment on lines +478 to +488
file_name: z.string().optional(),
file_path: z.string(),
size: z.coerce.number().optional(),
encoding: z.string().optional(),
content: z.string().optional(),
content_sha256: z.string().optional(),
ref: z.string().optional(),
blob_id: z.string().optional(),
commit_id: z.string().optional(),
last_commit_id: z.string().optional(),
execute_filemode: z.boolean().optional(),
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making all response fields optional in GitLabFileContentSchema could mask actual issues with the GitLab API responses. While this increases compatibility with older GitLab versions, it removes important validations. For example, file_path is the only guaranteed required field but making content, encoding, and size optional means the schema won't catch malformed responses where these critical fields are missing.

Consider keeping essential fields like content and encoding as required, or at least documenting which fields are expected to be present in a valid file response. If certain fields are truly optional only for directory responses, consider using a discriminated union instead.

Copilot uses AI. Check for mistakes.
})
.transform(data => ({
project_id: (data.project_id ?? "").trim(),
file_path: (data.file_path ?? data.path ?? "").trim(),
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The transform could return an empty file_path string when neither file_path nor path is provided, bypassing the superRefine validation. The superRefine validator checks if both fields are missing and adds an error, but the transform runs after validation passes. If both fields contain only whitespace, trim will produce an empty string, which could cause issues downstream in the getFileContents function.

Consider adding validation to ensure the resulting file_path after trimming is not empty, or handling empty strings in the getFileContents function.

Copilot uses AI. Check for mistakes.
Comment on lines +1064 to +1065
file_path: z.string().optional().describe("Path to the file or directory"),
path: z.string().optional().describe("Alias of file_path"),
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The schema now accepts both file_path and path parameters, but there's no clear precedence documented. While the transform uses file_path first and falls back to path, this behavior is not documented in the schema descriptions. MCP clients using this API need to understand which parameter takes precedence when both are provided.

Consider updating the description for at least one of these fields to document the precedence order, for example: "Path to the file or directory. Takes precedence over 'path' parameter if both are provided."

Copilot uses AI. Check for mistakes.
Copy link
Owner

@zereight zereight left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check some ai reviews?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants