Thank you for your interest in contributing! This guide will help you get started.
- Code of Conduct
- Getting Started
- Development Setup
- Branch Strategy
- Making Changes
- Commit Guidelines
- Pull Request Process
- Code Standards
- Testing
- Documentation
- Be respectful and constructive
- Welcome newcomers and help them learn
- Focus on the code, not the person
- Accept feedback gracefully
We use GitHub Issues to track bugs and feature requests.
- Bugs: If you find a bug, please use the Bug Report template.
- Features: If you have an idea, please use the Feature Request template.
- Questions: For general questions, please use the Question template or GitHub Discussions.
Please search existing issues before opening a new one to avoid duplicates.
- Node.js 18+ (20.x recommended)
- npm 9+
- Git
# Fork the repository on GitHub, then clone your fork
git clone https://github.com/YOUR_USERNAME/mcmodding-mcp.git
cd mcmodding-mcp
# Add upstream remote
git remote add upstream https://github.com/OGMatrix/mcmodding-mcp.git
# Install dependencies
npm install# Development
npm run dev # Start with hot reload
npm run build # Compile TypeScript
npm run typecheck # Type checking only
npm run lint # ESLint
npm run lint:fix # Fix lint issues
npm run format # Prettier formatting
npm run format:check # Check formatting
# Testing
npm test # Run tests once
npm run test:watch # Watch mode
npm run test:coverage # With coverage report
# Documentation Indexing
npm run index-docs # Index with embeddings
npm run index-docs:prod # Full re-index for production
# Validation (runs before commit)
npm run validate # typecheck + lint + test + buildVS Code (Recommended):
- Install recommended extensions (prompt appears on open)
- Settings are pre-configured in
.vscode/
Other IDEs:
- Enable ESLint integration
- Enable Prettier for formatting
- Configure TypeScript language service
We use a two-branch workflow:
feature/* ──┐
├──► dev ──► Release PR ──► prod ──► Release
bugfix/* ──┘
| Branch | Purpose |
|---|---|
dev |
Active development, all PRs target here |
prod |
Production releases only |
feature/* |
New features |
bugfix/* |
Bug fixes |
docs/* |
Documentation updates |
# Sync with upstream
git checkout dev
git pull upstream dev
# Create feature branch
git checkout -b feature/my-awesome-feature
# Make changes, commit, push
git push -u origin feature/my-awesome-feature
# Create PR to dev (not prod!)- Create the handler in
src/tools/:
// src/tools/myNewTool.ts
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
export interface MyToolParams {
query: string;
limit?: number;
}
export async function handleMyTool(params: MyToolParams): Promise<CallToolResult> {
// Validate input
if (!params.query) {
return {
content: [{ type: 'text', text: 'Error: query is required' }],
isError: true,
};
}
// Implementation
const result = await doSomething(params.query);
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
};
}- Register in
src/index.ts:
// Add import
import { handleMyTool } from './tools/myNewTool.js';
// Add to tools list
{
name: 'my_new_tool',
description: 'Description of what this tool does',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' },
limit: { type: 'number', description: 'Max results' },
},
required: ['query'],
},
}
// Add handler case
case 'my_new_tool':
return handleMyTool({
query: args?.query as string,
limit: args?.limit as number,
});-
Add tests in
src/tools/myNewTool.test.ts -
Update README.md with usage examples
The indexer components are in src/indexer/:
| File | Purpose |
|---|---|
crawler.ts |
HTTP fetching and HTML parsing |
chunker.ts |
Text splitting and chunking |
embeddings.ts |
Semantic vector generation |
store.ts |
SQLite database operations |
sitemap.ts |
Sitemap parsing |
When modifying:
- Test with
npm run index-docs - Check memory usage with large datasets
- Ensure backward compatibility with existing databases
Services in src/services/ contain business logic:
| File | Purpose |
|---|---|
search-service.ts |
Search orchestration |
concept-service.ts |
Concept explanation logic |
search-utils.ts |
Query parsing utilities |
We use Conventional Commits for automatic changelog generation.
<type>(<scope>): <description>
[optional body]
[optional footer]
| Type | Description | Version Bump |
|---|---|---|
feat |
New feature | Minor |
fix |
Bug fix | Patch |
perf |
Performance improvement | Patch |
refactor |
Code refactoring | None |
docs |
Documentation | None |
style |
Code style (formatting) | None |
test |
Tests | None |
build |
Build system | None |
ci |
CI/CD | None |
chore |
Maintenance | None |
Common scopes (optional but helpful):
search- Search functionalityindexer- Documentation indexingtools- MCP toolsstore- Database operationsembeddings- Semantic searchversioning- Auto-update system
# Feature
git commit -m "feat(search): add fuzzy matching support"
# Bug fix
git commit -m "fix(indexer): handle malformed HTML gracefully"
# Performance
git commit -m "perf(embeddings): batch process in chunks of 500"
# Breaking change
git commit -m "feat(tools)!: rename search_docs to search_fabric_docs
BREAKING CHANGE: Tool name changed for clarity"
# Multi-line with body
git commit -m "fix(chunker): prevent infinite loop on edge cases
The chunker could enter an infinite loop when overlap size
exceeded the content length. Added bounds checking to ensure
forward progress is always made."# Ensure everything passes
npm run validate
# Check for any TODOs you forgot
grep -r "TODO" src/When you open a Pull Request, a template will automatically load. Please fill out all sections:
- Description: What changed and why.
- Related Issue: Link to the issue (e.g.,
Fixes #123). - Type of Change: Check the appropriate box.
- Checklist: Ensure you've completed all steps.
- Branch is based on latest
dev - All tests pass (
npm test) - Code is formatted (
npm run format) - No lint errors (
npm run lint) - Types are correct (
npm run typecheck) - Commits follow conventional format
- PR targets
devbranch (notprod) - Description explains the changes
- Documentation updated if needed
Use conventional commit format:
feat(search): add category filtering
fix(indexer): resolve memory leak in crawler
docs: update installation instructions
## Summary
Brief description of what this PR does and why.
## Changes
- List of specific changes
- Another change
## Testing
How you tested these changes:
- [ ] Unit tests added/updated
- [ ] Manual testing performed
- [ ] Edge cases considered
## Screenshots (if applicable)
## Related Issues
Fixes #123
Related to #456- Submit PR to
dev - CI runs automatically
- Maintainer reviews code
- Address feedback if needed
- Maintainer merges when approved
// Use explicit types for function parameters and returns
function processData(input: string, options?: ProcessOptions): ProcessResult {
// Implementation
}
// Use interfaces for object shapes
interface ProcessOptions {
maxLength?: number;
format?: 'json' | 'text';
}
// Use type for unions/intersections
type Result = Success | Failure;
// Avoid `any` - use `unknown` if type is truly unknown
function handleUnknown(data: unknown): void {
if (typeof data === 'string') {
// Now TypeScript knows it's a string
}
}// Use try-catch for async operations
try {
const result = await fetchData();
return { success: true, data: result };
} catch (error) {
console.error('[ModuleName] Error:', error);
return { success: false, error: String(error) };
}
// Return structured errors from tool handlers
return {
content: [{ type: 'text', text: `Error: ${message}` }],
isError: true,
};// Files: kebab-case
// src/tools/search-docs.ts
// Classes: PascalCase
class DocumentStore {}
// Functions/methods: camelCase
function searchDocuments() {}
// Constants: SCREAMING_SNAKE_CASE
const MAX_CHUNK_SIZE = 1000;
// Interfaces: PascalCase with descriptive names
interface SearchResult {}
interface SearchOptions {}import { describe, it, expect, beforeEach, vi } from 'vitest';
import { myFunction } from './myModule.js';
describe('myFunction', () => {
beforeEach(() => {
// Setup before each test
});
it('should return expected result for valid input', () => {
const result = myFunction('valid input');
expect(result).toBe('expected output');
});
it('should handle edge cases', () => {
expect(myFunction('')).toBe('default');
expect(myFunction(null as any)).toThrow();
});
it('should work with async operations', async () => {
const result = await myAsyncFunction();
expect(result).toMatchObject({ status: 'success' });
});
});- Aim for >80% coverage on new code
- All bug fixes should include regression tests
- Test edge cases and error conditions
# Run all tests
npm test
# Watch mode (re-runs on changes)
npm run test:watch
# With coverage report
npm run test:coverage/**
* Search the documentation index for relevant content.
*
* Uses a hybrid approach combining FTS5 full-text search
* with semantic embeddings for best results.
*
* @param query - The search query string
* @param options - Optional search filters
* @returns Array of search results sorted by relevance
* @throws {DatabaseError} If the database connection fails
*
* @example
* ```typescript
* const results = await searchDocs('mixin tutorial', {
* category: 'getting-started',
* limit: 10,
* });
* ```
*/
export async function searchDocs(query: string, options?: SearchOptions): Promise<SearchResult[]> {
// Implementation
}Update the README when:
- Adding new tools or features
- Changing configuration options
- Modifying installation steps
- Adding new dependencies
- Bug reports: Open an issue
- Feature requests: Open an issue
- Questions: Start a discussion
Every contribution helps make Minecraft modding with AI assistants better for the entire community. We appreciate your time and effort!