Thank you for considering contributing to the GitHub MCP Server! This document provides guidelines and instructions for contributing.
Be respectful, inclusive, and professional in all interactions.
- Node.js 18+
- Git
- GitHub account
- GitHub Personal Access Token for testing
-
Fork the repository
-
Clone your fork:
git clone https://github.com/your-username/mcp-deployable.git cd mcp-deployable -
Install dependencies:
npm install
-
Set up environment:
export GITHUB_TOKEN="your_github_token"
-
Build the project:
npm run build
-
Run tests:
npm test
-
Create a new branch:
git checkout -b feature/your-feature-name
-
Make your changes following our coding standards
-
Write or update tests
-
Ensure all tests pass:
npm test -
Build to verify:
npm run build
-
Commit your changes:
git commit -m "feat: add new feature"
We follow Conventional Commits:
feat:- New featurefix:- Bug fixdocs:- Documentation changestest:- Test changesrefactor:- Code refactoringchore:- Maintenance tasksperf:- Performance improvements
Examples:
feat: add support for GitHub Issues
fix: handle rate limit errors correctly
docs: update deployment guide
test: add tests for merge_pr tool
-
Update documentation if needed
-
Add tests for new features
-
Ensure all tests pass
-
Update CHANGELOG.md
-
Push to your fork:
git push origin feature/your-feature-name
-
Create a Pull Request with:
- Clear title describing the change
- Detailed description of what and why
- Link to related issues
- Screenshots if UI changes
- Use strict TypeScript configuration
- Define types for all parameters and return values
- Avoid
anytype unless absolutely necessary - Use meaningful variable and function names
// Good
async function getPullRequest(params: GetPRParams): Promise<PullRequest> {
const response = await this.octokit.rest.pulls.get({
owner: params.owner,
repo: params.repo,
pull_number: params.pull_number,
});
return this.mapPullRequest(response.data);
}
// Bad
async function getPR(p: any): Promise<any> {
const r = await this.octokit.rest.pulls.get(p);
return r.data;
}All tool inputs must use Zod schemas:
export const NewToolSchema = z.object({
owner: z.string().min(1, 'Owner is required'),
repo: z.string().min(1, 'Repository name is required'),
// ... more fields
});Always catch and transform errors:
try {
// operation
} catch (error: any) {
throw this.handleError(error);
}Write tests for new features:
describe('New Tool', () => {
it('should validate input correctly', () => {
const validInput = { /* ... */ };
const result = NewToolSchema.safeParse(validInput);
expect(result.success).toBe(true);
});
it('should reject invalid input', () => {
const invalidInput = { /* ... */ };
const result = NewToolSchema.safeParse(invalidInput);
expect(result.success).toBe(false);
});
});To add a new GitHub operation as a tool:
Add to src/types/github.ts:
export interface NewToolParams {
owner: string;
repo: string;
// ... parameters
}
export interface NewToolResult {
// ... result fields
}Add to src/server/schemas/tools.ts:
export const NewToolSchema = z.object({
owner: z.string().min(1, 'Owner is required'),
repo: z.string().min(1, 'Repository name is required'),
// ... more fields
});
export type NewToolInput = z.infer<typeof NewToolSchema>;Add to src/server/tools/github-tools.ts:
async newTool(params: NewToolParams): Promise<NewToolResult> {
try {
const response = await this.octokit.rest./* api call */;
return /* mapped result */;
} catch (error: any) {
throw this.handleError(error);
}
}Add to src/server/index.ts:
// In TOOLS array
{
name: 'new_tool',
description: 'Description of what the tool does',
inputSchema: {
type: 'object',
properties: {
// ... JSON Schema
},
required: ['owner', 'repo'],
},
}
// In CallToolRequestSchema handler
case 'new_tool': {
const params = NewToolSchema.parse(args);
result = await githubTools.newTool(params);
break;
}Add to src/worker.ts:
// In TOOLS array
{
name: 'new_tool',
description: 'Description',
}
// In switch statement
case 'new_tool': {
const params = NewToolSchema.parse(args);
result = await githubTools.newTool(params);
break;
}Add to tests/golden/github-tools.test.ts:
describe('New Tool', () => {
it('should validate new_tool input', () => {
const validInput = { /* ... */ };
const result = NewToolSchema.safeParse(validInput);
expect(result.success).toBe(true);
});
// More tests...
});- Add example to
EXAMPLES.md - Update tool list in
README.md - Add to
QUICKSTART.mdif relevant
Test individual components:
npm testTest with known-good data:
npm run test:goldenTest with the example client:
npm run clientFor testing against real GitHub API:
- Use a test repository
- Create test PRs
- Run operations
- Verify results
- Clean up test data
- Use JSDoc for public APIs
- Explain complex logic
- Document assumptions and edge cases
/**
* Merge a pull request using the specified method
* @param params - Merge parameters
* @returns Merge result with SHA and status
* @throws Error if PR is not mergeable or conflicts exist
*/
async mergePR(params: MergePRParams): Promise<MergeResult> {
// implementation
}Update documentation when:
- Adding new features
- Changing APIs
- Modifying setup process
- Adding dependencies
- Minimize API calls
- Use appropriate filters
- Cache when possible
- Handle rate limits gracefully
- Never commit tokens or secrets
- Validate all inputs
- Sanitize error messages
- Use least privilege access
- Follow GitHub's security best practices
Maintainers handle releases:
- Update version in
package.json - Update
CHANGELOG.md - Create git tag
- Publish to npm (if applicable)
- Create GitHub release
- Check existing issues and PRs
- Read documentation thoroughly
- Ask in GitHub Discussions
- Be specific about your question
Contributors will be:
- Listed in CHANGELOG.md
- Mentioned in release notes
- Added to contributors list
By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing! 🎉