railway-mcp

by jason-tan-swe
Verified
# Contributing to Railway MCP Server ## Table of Contents - [Introduction](#introduction) - [Why Contribute?](#why-contribute) - [Getting Started](#getting-started) - [Prerequisites](#prerequisites) - [First-time Setup](#first-time-setup) - [Project Structure](#project-structure) - [Development Workflow](#development-workflow) - [Branch Strategy](#branch-strategy) - [Commit Messages](#commit-messages) - [TypeScript Guidelines](#typescript-guidelines) - [Testing Requirements](#testing-requirements) - [Contribution Process](#contribution-process) - [Find or Create an Issue](#find-or-create-an-issue) - [Make Changes](#make-changes) - [Submit Changes](#submit-changes) - [Code Review](#code-review) - [Debugging](#debugging) - [Development Debugging with MCP Inspector](#development-debugging-with-mcp-inspector) - [Production Debugging](#production-debugging) - [Additional Resources](#additional-resources) - [Example Implementations](#example-implementations) - [Tool Implementation](#1-tool-implementation-srctoolsexampletoolts) - [Service Implementation](#2-service-implementation-srcservicesexampleservicets) - [Repository Implementation](#3-repository-implementation-srcapirepositoryexamplerepots) ## Introduction Railway MCP Server is a Model Context Protocol (MCP) server that enables AI agents to manage Railway.app infrastructure through natural language. Our goal is to make infrastructure management more accessible and efficient through AI-powered automation. ### Why Contribute? Your contributions help make Railway infrastructure management more accessible to AI agents and their users. We welcome: - Code contributions (new tools, API integrations) - Documentation improvements - Bug reports and fixes - Feature requests and ideas - Testing and feedback ## Getting Started ### Prerequisites - Node.js 18+ (required for built-in fetch API) - TypeScript 5.8+ - npm or yarn - A Railway.app account and API token - Basic understanding of GraphQL and MCP ### First-time Setup 1. **Fork & Clone** ```bash git clone https://github.com/jason-tan-swe/railway-mcp.git cd railway-mcp npm install ``` 2. **Verify Setup** ```bash npm run build npm run dev # Starts the server with MCP Inspector ``` ### Project Structure ``` src/ ├── api/ # API-related code and GraphQL operations ├── services/ # Core business logic and service implementations ├── tools/ # MCP tool implementations ├── utils/ # Shared utilities and helper functions ├── types.ts # TypeScript type definitions └── index.ts # Main entry point ``` ## Development Workflow ### Branch Strategy - `main` - Production-ready code - `feature/*` - New features - `fix/*` - Bug fixes - `docs/*` - Documentation updates ### Commit Messages We follow the [Conventional Commits](https://www.conventionalcommits.org/) specification: - `feat:` - New features - `fix:` - Bug fixes - `docs:` - Documentation changes - `chore:` - Maintenance tasks - `test:` - Test-related changes ### TypeScript Guidelines - Use strict type checking - Avoid `any` types unless absolutely necessary - Document complex types in `types.ts` - Use interfaces for API responses and tool parameters ### Testing Requirements 1. Write tests for new tools and API integrations 2. Test error handling scenarios 3. Verify type safety 4. Test with MCP Inspector before submitting PRs ## Contribution Process 1. **Find or Create an Issue** - Check existing issues or create a new one - Get approval for new features before starting 2. **Make Changes** - Create a new branch: `git checkout -b feature/your-feature` - Follow code style and TypeScript guidelines - Add necessary tests - Update documentation 3. **Submit Changes** - Push to your fork: `git push origin feature/your-feature` - Create a pull request - Link related issues - Provide clear description of changes 4. **Code Review** - Address review feedback - Ensure CI checks pass - Keep commits clean and focused ## Debugging ### Development Debugging with MCP Inspector The MCP Inspector is our primary development debugging tool. Learn more about it [here](https://modelcontextprotocol.io/docs/tools/inspector). 1. **Running the Inspector** ```bash npm run dev ``` 2. **Key Features** - Server Connection monitoring - Tool testing interface - Real-time logs and notifications - Resource inspection 3. **Development Flow** 1. Start Inspector with server 2. Make code changes 3. Auto-rebuild triggers 4. Test in Inspector 5. Monitor logs 4. **Testing with MCP Clients** To test your development server with MCP clients (like Claude for Desktop), you need to modify the client's configuration to point to your local development build: ```json { "mcpServers": { "railway": { "command": "node", "args": ["/YOUR/PATH/TO/railway-mcp/build/index.js"], "env": { "RAILWAY_API_TOKEN": "your-railway-token", "DEBUG": "railway:*" } } } } ``` > **Important**: The key difference for development testing is using `node /YOUR/PATH/TO/railway-mcp/build/index.js` instead of the NPM package. This ensures your MCP client runs your local development build. Steps for development testing: 1. Make your code changes 2. Run `npm run build` to compile 3. Your MCP client will use the newly built code While the exact configuration may vary by MCP client, the principle remains the same: point the client to your local `build/index.js` file instead of the published package. ### Production Debugging To enable debug logging in production: 1. Configure your MCP client's environment: ```json { "mcpServers": { "railway": { "command": "npx", "args": ["-y", "@jasontanswe/railway-mcp"], "env": { "RAILWAY_API_TOKEN": "your-token", "DEBUG": "railway:*" } } } } ``` 2. Available debug options: - `railway:*` - All debug logs - `railway:api` - API request/response logs - `railway:tools` - Tool execution logs 3. Monitor logs: ```bash tail -n 20 -F ~/Library/Logs/Claude/mcp-server-railway.log ``` ## Additional Resources - [Railway.app Documentation](https://docs.railway.app/) - [MCP Specification](https://modelcontextprotocol.io/) - [TypeScript Documentation](https://www.typescriptlang.org/docs/) - [GraphQL Documentation](https://graphql.org/learn/) ## Example Implementations Our codebase follows a three-layer architecture for implementing MCP tools: 1. **Tool Layer** (`tools/`) - Defines the tool interface and parameters 2. **Service Layer** (`services/`) - Implements business logic and handles responses 3. **Repository Layer** (`api/repository/`) - Manages GraphQL API interactions Here's how these layers work together: ### 1. Tool Implementation (`src/tools/example.tool.ts`) ```typescript import { z } from 'zod'; import { createTool, formatToolDescription } from '@/utils/tools'; import { exampleService } from '@/services/example.service'; export const exampleTools = [ createTool( "example-action", formatToolDescription({ type: 'API', description: "Description of what this tool does", bestFor: [ "Use case 1", "Use case 2" ], notFor: [ "Anti-pattern 1" ], relations: { prerequisites: ["required-tool"], alternatives: ["alternative-tool"], nextSteps: ["next-tool"], related: ["related-tool"] } }), { param1: z.string().describe("Description of parameter 1"), param2: z.number().optional().describe("Optional parameter 2"), }, async ({ param1, param2 }) => { return exampleService.performAction(param1, param2); } ) ]; ``` ### 2. Service Implementation (`src/services/example.service.ts`) ```typescript import { BaseService } from '@/services/base.service'; import { createSuccessResponse, createErrorResponse, formatError } from '@/utils/responses'; export class ExampleService extends BaseService { async performAction(param1: string, param2?: number) { try { const result = await this.client.example.someAction(param1, param2); return createSuccessResponse({ text: `Action completed: ${result}`, data: result }); } catch (error) { return createErrorResponse(`Error: ${formatError(error)}`); } } } // Initialize and export the singleton instance export const exampleService = new ExampleService(); ``` ### 3. Repository Implementation (`src/api/repository/example.repo.ts`) ```typescript import { RailwayApiClient } from '@/api/api-client'; import { ExampleResponse } from '@/types'; export class ExampleRepository { constructor(private client: RailwayApiClient) {} async someAction(param1: string, param2?: number): Promise<ExampleResponse> { const query = ` mutation exampleAction($param1: String!, $param2: Int) { exampleAction(input: { param1: $param1, param2: $param2 }) { id status result } } `; const data = await this.client.request<{ exampleAction: ExampleResponse }>( query, { param1, param2 } ); return data.exampleAction; } } ``` This architecture provides several benefits: - Clear separation of concerns - Type-safe interfaces between layers - Centralized error handling - Consistent response formatting - Reusable business logic - Isolated GraphQL operations When adding new functionality: 1. Define the tool interface in a tool file 2. Implement business logic in a service 3. Add GraphQL operations in a repository 4. Update types in `types.ts` as needed