Skip to main content
Glama

OPNSense MCP Server

DEVELOPER-GUIDE.md12.4 kB
# Developer Onboarding Guide - OPNSense MCP Server ## 🎯 Welcome to the Team! This guide will get you productive with the OPNSense MCP Server codebase in under 30 minutes. ## 📋 Prerequisites Checklist Before starting, ensure you have: - [ ] Node.js v18+ installed (`node --version`) - [ ] npm or yarn installed (`npm --version`) - [ ] Git configured (`git config --list`) - [ ] VS Code or preferred IDE - [ ] Access to an OPNsense instance (or test environment) - [ ] Basic TypeScript knowledge - [ ] Understanding of async/await patterns ## 🚀 Quick Start (5 minutes) ```bash # 1. Clone the repository git clone https://github.com/yourorg/opnsense-mcp-server.git cd opnsense-mcp-server # 2. Install dependencies npm install # 3. Copy environment template cp .env.example .env # 4. Configure your OPNsense connection nano .env # Set: # OPNSENSE_HOST=https://192.168.1.1 # OPNSENSE_API_KEY=your-key # OPNSENSE_API_SECRET=your-secret # 5. Build the project npm run build # 6. Run in development mode npm run dev # 7. Test the connection npm run test:connection ``` ## 🏗️ Architecture Overview ### Core Concepts ``` ┌─────────────┐ ┌──────────┐ ┌────────────┐ │ MCP Client │────▶│ Tools │────▶│ Resources │ └─────────────┘ └──────────┘ └────────────┘ │ │ ▼ ▼ ┌──────────┐ ┌────────────┐ │ Cache │ │ API Client │ └──────────┘ └────────────┘ │ ▼ ┌────────────┐ │ OPNsense │ └────────────┘ ``` ### Key Components 1. **Tools** (`src/tools/`): MCP tool implementations that clients call 2. **Resources** (`src/resources/`): Domain objects for CRUD operations 3. **API Client** (`src/api/client.ts`): Handles OPNsense API communication 4. **Cache** (`src/cache/`): Performance optimization layer 5. **State** (`src/state/`): Persistent state management for IaC ## 📁 Project Structure ``` src/ ├── api/ # API client and authentication ├── cache/ # Caching implementations │ ├── manager.ts # Basic cache │ └── enhanced-manager.ts # Advanced with compression ├── resources/ # Domain resources │ ├── network/ # VLANs, interfaces, ARP │ ├── firewall/ # Rules, aliases │ ├── services/ # DHCP, DNS, HAProxy │ └── base.ts # Base resource classes ├── tools/ # MCP tool definitions ├── types/ # TypeScript type definitions ├── utils/ # Utility functions └── index.ts # Main entry point ``` ## 🔨 Development Workflow ### 1. Creating a New Resource ```typescript // src/resources/services/new-service.ts import { BaseResource } from '../base'; import { z } from 'zod'; // Define the schema const NewServiceSchema = z.object({ name: z.string(), enabled: z.boolean(), port: z.number().min(1).max(65535) }); export class NewServiceResource extends BaseResource { async list(): Promise<NewService[]> { return await this.client.get('/api/services/newservice/list'); } async create(data: z.infer<typeof NewServiceSchema>): Promise<{uuid: string}> { const validated = NewServiceSchema.parse(data); return await this.client.post('/api/services/newservice/add', validated); } } ``` ### 2. Adding a New Tool ```typescript // src/tools/new-service.ts import { z } from 'zod'; // Define input schema const CreateNewServiceSchema = z.object({ name: z.string().describe('Service name'), port: z.number().describe('Service port') }); // Register the tool server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === 'opnsense_newservice_create') { const args = CreateNewServiceSchema.parse(request.params.arguments); const resource = new NewServiceResource(this.client); const result = await resource.create(args); return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } }); ``` ### 3. Testing Your Changes ```typescript // test/unit/resources/new-service.test.ts import { describe, it, expect, jest } from '@jest/globals'; import { NewServiceResource } from '../../../src/resources/services/new-service'; describe('NewServiceResource', () => { it('should create a service', async () => { const mockClient = { post: jest.fn().mockResolvedValue({ uuid: 'test-123' }) }; const resource = new NewServiceResource(mockClient); const result = await resource.create({ name: 'test', enabled: true, port: 8080 }); expect(result.uuid).toBe('test-123'); expect(mockClient.post).toHaveBeenCalledWith( '/api/services/newservice/add', expect.objectContaining({ name: 'test' }) ); }); }); ``` ## 🐛 Debugging Tips ### Enable Debug Logging ```bash # Set environment variables export DEBUG=opnsense:* export LOG_LEVEL=debug # Run with verbose output npm run dev -- --verbose ``` ### Use VS Code Debugger ```json // .vscode/launch.json { "version": "0.2.0", "configurations": [ { "type": "node", "request": "launch", "name": "Debug MCP Server", "skipFiles": ["<node_internals>/**"], "program": "${workspaceFolder}/dist/index.js", "preLaunchTask": "npm: build", "outFiles": ["${workspaceFolder}/dist/**/*.js"], "env": { "DEBUG": "opnsense:*", "NODE_ENV": "development" } } ] } ``` ### Common Debugging Scenarios ```typescript // Add debug points in your code console.log('[DEBUG] API Request:', { endpoint, payload }); // Use the debugger statement debugger; // Execution will pause here when debugging // Conditional debugging if (process.env.DEBUG) { console.log('Detailed info:', detailedObject); } // Performance debugging console.time('api-call'); const result = await apiClient.call(); console.timeEnd('api-call'); ``` ## 📚 Code Style Guide ### TypeScript Best Practices ```typescript // ✅ DO: Use explicit types interface VlanConfig { tag: number; interface: string; description?: string; } // ❌ DON'T: Use any let config: any = { tag: 100 }; // ✅ DO: Use async/await async function createVlan(config: VlanConfig) { try { const result = await client.createVlan(config); return result; } catch (error) { handleError(error); } } // ❌ DON'T: Use callbacks or .then() function createVlan(config, callback) { client.createVlan(config).then(callback); } ``` ### Error Handling ```typescript // ✅ DO: Throw typed errors class VlanNotFoundError extends Error { constructor(public readonly tag: number) { super(`VLAN ${tag} not found`); this.name = 'VlanNotFoundError'; } } // ✅ DO: Handle specific errors try { await vlanResource.delete(tag); } catch (error) { if (error instanceof VlanNotFoundError) { console.log('VLAN already deleted'); } else { throw error; // Re-throw unexpected errors } } ``` ### Validation ```typescript // ✅ DO: Validate inputs with Zod const schema = z.object({ port: z.number().min(1).max(65535), protocol: z.enum(['tcp', 'udp']) }); const validated = schema.parse(input); // Throws if invalid // ✅ DO: Use safeParse for user input const result = schema.safeParse(userInput); if (!result.success) { return { error: result.error.errors }; } ``` ## 🧪 Testing Guidelines ### Test Structure ```typescript describe('Component/Feature', () => { describe('methodName', () => { it('should do something specific', () => { // Arrange const input = setupTestData(); // Act const result = performAction(input); // Assert expect(result).toEqual(expectedOutput); }); it('should handle error case', () => { // Test error scenarios }); }); }); ``` ### Running Tests ```bash # Run all tests npm test # Run specific test file npm test -- new-service.test.ts # Run with coverage npm run test:coverage # Run in watch mode npm run test:watch # Debug tests npm run test:debug ``` ## 🔄 Git Workflow ### Branch Naming ```bash feature/add-dns-management bugfix/vlan-validation-error hotfix/api-connection-timeout refactor/consolidate-cache-managers docs/update-api-examples ``` ### Commit Messages ```bash # Format: <type>(<scope>): <subject> feat(vlan): add support for QoS priority fix(firewall): correct rule ordering issue docs(api): update examples for new endpoints refactor(cache): consolidate manager implementations test(resources): add unit tests for DHCP resource ``` ### Pull Request Process 1. Create feature branch 2. Make changes with tests 3. Run linting: `npm run lint` 4. Run tests: `npm test` 5. Commit with conventional message 6. Push and create PR 7. Address review comments 8. Merge after approval ## 🚢 Deployment ### Local Development ```bash npm run dev # Development with hot reload npm run build # Build for production npm start # Run production build ``` ### Docker ```bash # Build image docker build -t opnsense-mcp . # Run container docker run -d \ -e OPNSENSE_HOST=$OPNSENSE_HOST \ -e OPNSENSE_API_KEY=$OPNSENSE_API_KEY \ -e OPNSENSE_API_SECRET=$OPNSENSE_API_SECRET \ -p 3000:3000 \ opnsense-mcp ``` ### Production ```bash # Using PM2 pm2 start ecosystem.config.js pm2 logs opnsense-mcp pm2 monit # Health check curl http://localhost:3000/health ``` ## 📖 Learning Resources ### Internal Documentation - [Architecture Overview](./ARCHITECTURE.md) - [API Examples](./API-EXAMPLES.md) - [Security Guide](./SECURITY-AUDIT.md) - [Performance Guide](./PERFORMANCE-ANALYSIS.md) - [Troubleshooting](./TROUBLESHOOTING.md) ### External Resources - [MCP SDK Documentation](https://modelcontextprotocol.io) - [OPNsense API Docs](https://docs.opnsense.org/development/api.html) - [TypeScript Handbook](https://www.typescriptlang.org/docs) - [Zod Documentation](https://zod.dev) ### Code Examples Check the `examples/` directory for: - Basic CRUD operations - Batch processing - Error handling patterns - Testing examples - Performance optimization ## 🤝 Getting Help ### Team Contacts - **Tech Lead**: @techlead (Slack) - **DevOps**: @devops-team (Slack) - **Code Reviews**: #code-reviews (Slack) ### Resources - **Wiki**: [Internal Wiki](https://wiki.company.com/opnsense-mcp) - **Issues**: [GitHub Issues](https://github.com/yourorg/opnsense-mcp/issues) - **CI/CD**: [Jenkins Dashboard](https://jenkins.company.com/opnsense-mcp) ### Office Hours - **Monday**: 2-3 PM - Architecture discussions - **Wednesday**: 10-11 AM - Code review session - **Friday**: 3-4 PM - Open Q&A ## 🎉 Your First Tasks As a new developer, here are good first issues to tackle: 1. **Add input validation** to an existing tool 2. **Write unit tests** for a resource class 3. **Fix a documentation** issue 4. **Implement a simple tool** (like listing operations) 5. **Improve error messages** in a specific module Look for issues tagged with `good-first-issue` in GitHub. ## 📈 Performance Tips 1. **Always use the cache** for read operations 2. **Batch API calls** when possible 3. **Use compression** for large payloads (already implemented) 4. **Profile before optimizing** - don't guess 5. **Monitor memory usage** in production ## 🔐 Security Reminders 1. **Never log sensitive data** (API keys, passwords) 2. **Validate all inputs** with Zod schemas 3. **Use encryption** for state storage (implemented) 4. **Follow OWASP guidelines** for web security 5. **Regular dependency updates** with `npm audit` --- *Welcome aboard! We're excited to have you contributing to the OPNSense MCP Server. Don't hesitate to ask questions - we're here to help you succeed!*

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vespo92/OPNSenseMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server