We love your input! We want to make contributing to 1MCP as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer
- Development Process
- Getting Started
- Pull Request Process
- Issue Guidelines
- Coding Standards
- Testing Guidelines
- Platform-Specific Contributions
- Documentation Guidelines
- Community Guidelines
We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
- Fork the repo and create your branch from
main - If you've added code that should be tested, add tests
- If you've changed APIs, update the documentation
- Ensure the test suite passes
- Make sure your code lints
- Issue that pull request!
- Node.js 18+ or 20+
- pnpm (recommended) or npm
- TypeScript 5.3+
- Git
- @modelcontextprotocol/sdk ^1.15.0 (automatically installed)
-
Fork and Clone
# Fork the repository on GitHub, then clone your fork git clone https://github.com/1mcp-app/agent.git cd agent
-
Install Dependencies
pnpm install
-
Build the Project
pnpm build
-
Run Tests
# Run unit tests pnpm test:unit # Run E2E tests pnpm test:e2e # Run all tests pnpm test:unit && pnpm test:e2e
-
Start Development Server
pnpm dev
Understanding the codebase structure will help you contribute effectively. The project follows a layered architecture with clear separation of concerns:
agent/
├── src/
│ ├── application/ # Application-level services
│ │ └── services/ # Cross-cutting orchestration services
│ │ ├── configReloadService.ts
│ │ ├── healthService.ts
│ │ └── tokenEstimationService.ts
│ ├── auth/ # Authentication & OAuth 2.1 system
│ │ ├── storage/ # Repository pattern for auth data
│ │ ├── sdkOAuthClientProvider.ts
│ │ ├── sdkOAuthServerProvider.ts
│ │ └── sessionTypes.ts
│ ├── commands/ # CLI command implementations
│ │ ├── app/ # App management commands
│ │ ├── mcp/ # MCP server management commands
│ │ ├── preset/ # Preset management commands
│ │ ├── proxy/ # Proxy commands
│ │ ├── serve/ # Server commands
│ │ └── shared/ # Shared command utilities
│ ├── config/ # Configuration management
│ │ ├── configContext.ts
│ │ ├── mcpConfigManager.ts
│ │ ├── envProcessor.ts
│ │ ├── projectConfigLoader.ts
│ │ └── projectConfigTypes.ts
│ ├── constants/ # Domain-organized constants
│ │ ├── api.ts # API endpoints, ports, hosts
│ │ ├── auth.ts # Authentication constants
│ │ ├── mcp.ts # MCP protocol constants
│ │ ├── paths.ts # File paths, directories
│ │ └── index.ts # Barrel export
│ ├── core/ # Core business logic
│ │ ├── capabilities/ # MCP capability management
│ │ ├── client/ # Client management
│ │ ├── filtering/ # Request filtering logic
│ │ ├── instructions/ # Template engine
│ │ ├── loading/ # Async loading orchestration
│ │ ├── notifications/ # Notification system
│ │ ├── protocol/ # Protocol message handlers
│ │ ├── server/ # Server lifecycle management
│ │ └── types/ # Shared type definitions
│ ├── domains/ # Domain modules
│ │ ├── backup/ # Backup management domain
│ │ ├── discovery/ # App discovery domain
│ │ └── preset/ # Preset management domain
│ │ ├── manager/ # PresetManager
│ │ ├── parsers/ # Tag query parsing
│ │ ├── services/ # Preset services
│ │ └── types/ # Preset types
│ ├── logger/ # Logging infrastructure
│ │ ├── configureGlobalLogger.ts
│ │ └── [6 other logger files]
│ ├── transport/ # Transport layer implementations
│ │ ├── http/ # HTTP/SSE transport
│ │ │ ├── server.ts # Express server implementation
│ │ │ ├── routes/ # HTTP endpoint handlers
│ │ │ │ ├── oauthRoutes.ts # OAuth endpoint handlers
│ │ │ │ ├── sseRoutes.ts # Server-sent events routes
│ │ │ │ └── streamableHttpRoutes.ts # HTTP streaming routes
│ │ │ └── middlewares/ # HTTP middleware functions
│ │ │ ├── errorHandler.ts # Error handling middleware
│ │ │ ├── scopeAuthMiddleware.ts # Scope-based authentication
│ │ │ ├── securityMiddleware.ts # Security middleware
│ │ │ └── tagsExtractor.ts # Tag extraction middleware
│ │ └── transportFactory.ts # Transport factory pattern
│ ├── utils/ # Generic utilities only
│ │ ├── core/ # Core utilities
│ │ ├── ui/ # CLI utilities
│ │ └── validation/ # Input validation
│ └── e2e/ # End-to-end tests
│ ├── demo/ # Infrastructure demonstration tests
│ ├── fixtures/ # Test server implementations
│ ├── http/ # HTTP transport integration tests
│ ├── integration/ # Multi-transport and performance tests
│ ├── setup/ # Global test setup/teardown
│ ├── stdio/ # STDIO transport tests
│ └── utils/ # Test utilities and helpers
├── docs/ # Documentation
│ ├── en/ # English documentation
│ ├── zh/ # Chinese documentation
│ └── plans/ # Development planning documents
├── test/ # Test files
└── build/ # Compiled output
- Application Layer (
application/): Cross-cutting orchestration services - Core Layer (
core/): Core business logic and domain entities - Domain Layer (
domains/): Self-contained business domains - Transport Layer (
transport/): Protocol implementations and communication - Infrastructure Layer (
auth/,config/,logger/): Cross-cutting infrastructure concerns
- Domain-Driven Design: Clear boundaries between business domains
- Layered Architecture: Dependencies flow inward (Application → Core → Domains)
- Co-location: Related files grouped together
- Barrel Exports: Clean import paths with
index.tsfiles
- Check for existing issues/PRs - Search for existing issues or pull requests related to your change
- Create an issue first - For significant changes, please create an issue to discuss the proposed changes
- Follow the coding standards - Ensure your code follows the project's coding standards
- Write tests - Add tests for any new functionality
- Update documentation - Update relevant documentation for your changes
-
Use a clear and descriptive title
Good: Add retry logic for MCP server connections Bad: Fix bug -
Provide a detailed description
- What changes were made and why
- Link to related issues
- Include screenshots for UI changes
- List any breaking changes
-
Follow the PR template
## Description Brief description of changes ## Type of Change - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update ## Testing - [ ] Tests pass locally - [ ] Added tests for new functionality - [ ] Manual testing completed ## Checklist - [ ] Code follows the style guidelines - [ ] Self-review completed - [ ] Documentation updated - [ ] No console.log statements left
-
Keep PRs focused - One feature/fix per PR when possible
-
Ensure CI passes - All automated checks must pass
- Automated Checks - CI must pass (tests, linting, build)
- Code Review - At least one maintainer must approve
- Testing - Manual testing may be required for complex changes
- Documentation Review - Documentation changes are reviewed for clarity and accuracy
Before creating a bug report, please check the existing issues to avoid duplicates.
Use this template for bug reports:
## Bug Description
A clear and concise description of the bug.
## Steps to Reproduce
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
## Expected Behavior
A clear description of what you expected to happen.
## Actual Behavior
A clear description of what actually happened.
## Environment
- OS: [e.g. macOS 14.0]
- Node.js version: [e.g. 20.10.0]
- 1MCP version: [e.g. 0.12.0]
- AI Client: [e.g. Claude Desktop, Cursor]
## Additional Context
Add any other context about the problem here.Use this template for feature requests:
## Feature Description
A clear and concise description of the feature you'd like to see.
## Problem Statement
What problem does this feature solve?
## Proposed Solution
Describe your proposed solution.
## Alternatives Considered
Describe any alternative solutions you've considered.
## Additional Context
Add any other context or screenshots about the feature request here.- Use TypeScript strict mode - All code must pass strict type checking
- Explicit types - Use explicit types for function parameters and return values
- Interfaces over types - Prefer interfaces for object types
- No
anytypes - Avoid usingany; use proper typing
// Good
interface ServerConfig {
name: string;
port: number;
enabled: boolean;
}
function createServer(config: ServerConfig): Promise<Server> {
// implementation
}
// Avoid
function createServer(config: any): any {
// implementation
}-
ESLint configuration - Follow the project's ESLint rules
-
Prettier formatting - Use Prettier for consistent formatting
-
Naming conventions:
camelCasefor variables and functionsPascalCasefor classes and interfacesUPPER_SNAKE_CASEfor constants
-
File organization:
- One class/interface per file
- Group related functionality
- Clear import organization
- Use specific error types - Create custom error classes when appropriate
- Proper error propagation - Don't swallow errors silently
- Logging - Use the project's logging system
// Good
import { ErrorType, MCPError } from './utils/errorTypes';
try {
await connectToServer();
} catch (error) {
logger.error('Failed to connect to server:', error);
throw new MCPError(ErrorType.CONNECTION_ERROR, 'Server connection failed', error);
}
// Avoid
try {
await connectToServer();
} catch (error) {
// Silent failure
}- Async/await - Use async/await over promises where possible
- Resource cleanup - Properly clean up resources (connections, timers, etc.)
- Memory management - Avoid memory leaks in long-running processes
- Test files - Place tests next to the code they test with
.test.tsextension - Test organization - Group related tests using
describeblocks - Test naming - Use descriptive test names
describe('ServerManager', () => {
describe('connectToServer', () => {
it('should successfully connect to a valid MCP server', async () => {
// Test implementation
});
it('should throw error when connection fails', async () => {
// Test implementation
});
});
});- Co-located unit tests - Place unit tests next to source files with
.test.tsextension - E2E test fixtures - Use dedicated test servers in
/test/e2e/fixtures/
- Unit Tests - Test individual functions/methods (co-located with source files)
- Integration Tests - Test component interactions (included in E2E suite)
- End-to-End Tests - Test complete workflows (separate test directory with fixtures)
We use Vitest as our testing framework:
- Unit Tests: Fast, parallel execution with coverage
- E2E Tests: Sequential execution with longer timeouts
- Coverage: V8 provider with HTML/JSON/text reporting
- Global Setup: E2E tests have dedicated setup/teardown infrastructure
- Arrange, Act, Assert - Structure tests clearly
- Mock external dependencies - Use mocks for external services
- Test edge cases - Include error conditions and boundary cases
- Cleanup - Clean up resources after tests
# Unit tests (fast, parallel)
pnpm test:unit
pnpm test:unit:watch
pnpm test:unit:coverage
# E2E tests (sequential, with fixtures)
pnpm test:e2e
pnpm test:e2e:watch
pnpm test:e2e:coverage
# Debug with MCP Inspector
pnpm inspector1MCP currently has different levels of support across platforms:
- 🟢 macOS (darwin): Fully tested and verified - primary development platform
- 🟡 Windows (win32): Paths researched but untested - community help needed
- 🟡 Linux: Paths researched but untested - community help needed
We urgently need contributors on Windows and Linux to help verify and improve platform support!
-
Test App Integration Paths
- Uncomment Windows sections in
src/utils/appPresets.ts - Test with apps like Claude Desktop, VS Code, Cursor
- Verify configuration file locations are correct
- Uncomment Windows sections in
-
Common Windows Paths to Verify:
Claude Desktop: %APPDATA%\Claude\claude_desktop_config.json VS Code: %APPDATA%\Code\User\settings.json Cursor: %APPDATA%\Cursor\User\settings.json
-
Test App Integration Paths
- Uncomment Linux sections in
src/utils/appPresets.ts - Test with apps that follow XDG Base Directory specification
- Verify paths match your distribution's conventions
- Uncomment Linux sections in
-
Common Linux Paths to Verify:
Claude Desktop: ~/.config/claude/claude_desktop_config.json VS Code: ~/.config/Code/User/settings.json Cursor: ~/.cursor/mcp.json
-
Fork and Setup
git clone https://github.com/YOUR-USERNAME/agent.git cd agent pnpm install -
Enable Platform Paths
- Edit
src/utils/appPresets.ts - Uncomment your platform's path configurations
- Build:
pnpm build
- Edit
-
Test App Discovery
# Test app discovery npx @1mcp/agent app discover # Test app listing npx @1mcp/agent app list # Test consolidation (if you have the apps installed) npx @1mcp/agent app consolidate claude-desktop
-
Report Results
- Create an issue with your findings
- Include your OS version, app versions, and test results
- Submit a PR with working path corrections
High Priority Apps (please test first):
- Claude Desktop
- VS Code
- Cursor
Medium Priority Apps:
- Cline (VS Code extension)
- Continue (VS Code extension)
- Roo Code
When reporting platform-specific issues, please use:
## Platform Testing Report
**Platform:** Windows 11 / Ubuntu 22.04 / etc.
**App:** Claude Desktop / VS Code / etc.
**1MCP Version:** [version number]
### Test Results
- [ ] App discovery works
- [ ] Configuration path is correct
- [ ] App consolidation works
- [ ] MCP servers integrate properly
### Issues Found
[Describe any problems encountered]
### Suggested Fixes
[Propose corrections if you found working paths]
### Additional Notes
[Any other relevant information]Add tests for your platform in the test suite:
describe('Platform-specific paths', () => {
it('should resolve Windows paths correctly', () => {
// Test Windows path resolution
});
it('should resolve Linux paths correctly', () => {
// Test Linux path resolution
});
});Consider platform differences:
- File system case sensitivity
- Path separators
- Environment variable conventions
- Default application installation locations
Platform contributors will be specifically recognized in:
- Release notes
- Platform support documentation
- Contributor acknowledgments
Your help makes 1MCP work for everyone! 🌍
import { vi } from 'vitest';
describe('ClientManager', () => {
afterEach(() => {
vi.clearAllMocks();
});
it('should retry failed connections with exponential backoff', async () => {
// Arrange
const mockTransport = vi.fn().mockRejectedValueOnce(new Error('Connection failed'));
// Act
const result = await clientManager.connect(mockTransport);
// Assert
expect(mockTransport).toHaveBeenCalledTimes(3);
});
});- JSDoc comments - Document public APIs
- Inline comments - Explain complex logic
- README updates - Update README for user-facing changes
/**
* Connects to an MCP server with retry logic and exponential backoff.
*
* @param transport - The transport configuration for the server
* @param options - Connection options including retry settings
* @returns Promise that resolves to the connected server instance
* @throws {MCPError} When connection fails after all retries
*/
async connectToServer(
transport: Transport,
options: ConnectionOptions = {}
): Promise<Server> {
// Implementation
}- Design decisions - Document significant architectural choices
- Patterns used - Explain design patterns and their benefits
- Data flow - Document how data flows through the system
- Clear examples - Provide working code examples
- Step-by-step guides - Break down complex procedures
- Troubleshooting - Include common issues and solutions
- Be respectful - Treat everyone with respect and kindness
- Be constructive - Provide helpful feedback and suggestions
- Be patient - Remember that maintainers are volunteers
- Ask questions - Don't hesitate to ask for clarification
- Check documentation - Review existing docs first
- Search issues - Look for existing discussions
- Create detailed issues - Provide context and examples
- Join discussions - Participate in community discussions
Current Version: 0.12.0
- Pre-commit hooks - Husky ensures code quality before commits
- Lint-staged - Only lint changed files for faster feedback
- Hot-reload - Development server with automatic rebuild
- Configuration hot-reload - MCP server configuration updates without restart
We value all contributions, including:
- Code contributions
- Documentation improvements
- Bug reports
- Feature suggestions
- Community support
- Testing and feedback
Contributors will be recognized in our release notes and contributor lists.
We follow Semantic Versioning:
- Major (1.0.0) - Breaking changes
- Minor (0.1.0) - New features, backwards compatible
- Patch (0.0.1) - Bug fixes, backwards compatible
All notable changes are documented in CHANGELOG.md following Keep a Changelog format.
By contributing, you agree that your contributions will be licensed under the same license as the project (Apache License 2.0).
If you have questions about contributing, please:
- Check the existing documentation
- Search through past issues
- Create a new issue with the question label
- Reach out to maintainers
Thank you for contributing to 1MCP! 🚀