This document provides technical information for local development and maintenance of the Upsun MCP Server.
Note: The Upsun MCP server is hosted and available at https://mcp.upsun.com/mcp. This guide is for developers who want to contribute to, customize, or run the server locally for development purposes.
- URL: https://mcp.upsun.com/mcp
- Purpose: Production-ready MCP server for end users
- Setup: Configure your MCP client to connect to the hosted service
- Maintenance: Managed by the Upsun team
- Purpose: Development, testing, and contribution to the codebase
- Setup: Clone repository, install dependencies, run locally
- Use cases: Adding features, fixing bugs, customizing behavior
# Development workflow
npm run build # Compile TypeScript
npm run watch # Watch mode for development
npm run test # Run test suite
npm run test:watch # Run tests in watch mode
npm run lint # Check code quality
npm run prettier # Format code# Required
UPSUN_API_KEY=your-api-token
# Write Operations (Beta Safety)
enable-write=true # Enable write ops via header
# Server Configuration
TYPE_ENV=local # stdio mode
TYPE_ENV=remote # HTTP/SSE mode (default)
PORT=3000 # Server port (remote mode)
# Debugging
LOG_LEVEL=DEBUG # DEBUG, INFO, WARN, ERROR, NONE
NODE_ENV=development # development, production, testCritical: This beta release defaults to read-only mode. Write operations are controlled by the enable-write header:
- Default: Read-only operations only
- Write enabled: Set
enable-write: trueheader in MCP client configuration
Example header configuration:
{
"headers": {
"upsun-api-token": "your-api-token",
"enable-write": "true"
}
}upsun-mcp/
├── src/
│ ├── core/ # Core MCP and infrastructure
│ │ ├── adapter.ts # MCP adapter interface
│ │ ├── gateway.ts # HTTP/SSE server
│ │ ├── authentication.ts # Bearer token & authentication handling
│ │ ├── logger.ts # Structured logging
│ │ ├── requestContext.ts # AsyncLocalStorage for Express res
│ │ └── helper.ts # Common utilities
│ ├── command/ # MCP tool implementations
│ │ ├── index.ts # Command exports
│ │ ├── project.ts # Project management
│ │ ├── environment.ts # Environment operations
│ │ ├── organization.ts # Organization tools
│ │ ├── activity.ts # Activity monitoring
│ │ ├── ssh.ts # SSH key management
│ │ ├── domain.ts # Domain configuration
│ │ ├── route.ts # Route management
│ │ ├── certificate.ts # SSL certificates
│ │ └── backup.ts # Backup operations
│ ├── task/ # MCP prompt implementations
│ │ ├── index.ts # Task exports
│ │ └── config.ts # Config generation prompts
│ ├── index.ts # Main entry point
│ └── mcpUpsun.ts # Primary MCP server class
├── test/ # Test suites (mirrors src/)
├── build/ # Compiled JavaScript output
├── package.json # Dependencies & scripts
├── tsconfig.json # TypeScript configuration
├── jest.config.ts # Test configuration
└── .env # Local environment variables
UpsunMcpServer: Main MCP server implementationMcpAdapter: Interface defining MCP server contractGatewayServer: HTTP/SSE transport with authentication handlingLocalServer: stdio transport for development
-
Local (stdio): Direct communication via stdin/stdout
TYPE_ENV=local npm run run
-
Remote (HTTP/SSE): Web server with HTTP authentication support
TYPE_ENV=remote PORT=3000 npm run run
- API Key: Direct authentication via
upsun-api-tokenheader - Bearer Token: Alternative authentication via
Authorization: Bearerheader - Write Control: Write operations controlled via
enable-writeheader - Upstream 401 forwarding: When the Upsun API returns 401 (expired/revoked token),
the HTTP transport forwards the 401 status and
WWW-Authenticateheader directly to the MCP client so it can trigger OAuth2 token refresh. This only works on the Streamable HTTP transport (enableJsonResponse: true); SSE commits 200 headers immediately so 401 forwarding is not possible there.
cd upsun-mcp
npm install
cp .env.example .env # Configure your API token# Terminal 1: Watch compilation
npm run watch
# Terminal 2: Run server in stdio mode
TYPE_ENV=local npm run run
# Terminal 3: Run tests in watch mode
npm run test:watch# Full test suite
npm test
# With coverage
npm run test:coverage
# Coverage verification
npm run coverage:check# Linting
npm run lint
npm run lint:fix
# Formatting
npm run prettier
npm run prettier:checkCreate src/command/newfeature.ts:
import { McpAdapter } from '../core/adapter.js';
import { Response, Schema } from '../core/helper.js';
import { createLogger } from '../core/logger.js';
import { z } from 'zod';
const log = createLogger('MCP:Tool:newfeature-commands');
export function registerNewFeature(adapter: McpAdapter): void {
log.info('Register NewFeature Handlers');
adapter.server.registerTool(
'action-newfeature',
{
description: 'Description of the action',
inputSchema: {
param1: z.string(),
param2: Schema.projectId().optional(),
},
},
async ({ param1, param2 }) => {
log.debug(`Action: ${param1}`);
const result = await adapter.client.newfeature.action(param1, param2);
return Response.json(result);
}
);
}Add to src/command/index.ts:
export * from './newfeature.js';Add to src/mcpUpsun.ts constructor:
import { registerNewFeature } from './command/index.js';
constructor() {
// ... existing registrations
registerNewFeature(this);
}Create test/command/newfeature.test.ts:
import { registerNewFeature } from '../../src/command/newfeature.js';
// ... test implementation- Each command module has corresponding tests
- Mock Upsun SDK client responses
- Test parameter validation and error handling
- Test full MCP server initialization
- Test transport layer functionality
- Test authentication flows
- Minimum 80% line coverage
- All command modules must be tested
- Critical paths require 100% coverage
LOG_LEVEL=DEBUG # Verbose debugging information
LOG_LEVEL=INFO # General operational info (default)
LOG_LEVEL=WARN # Warning conditions
LOG_LEVEL=ERROR # Error conditions only
LOG_LEVEL=NONE # No logging-
Authentication Issues:
LOG_LEVEL=DEBUG npm run run # Check token extraction and validation logs -
Transport Problems:
# Test stdio mode TYPE_ENV=local LOG_LEVEL=DEBUG npm run run # Test HTTP mode TYPE_ENV=remote LOG_LEVEL=DEBUG npm run run
-
SDK Integration:
# Enable SDK debug logging in test environment
- Never log full API tokens (automatically masked)
- Store tokens in environment variables, never in code
- Use separate tokens for development/production
- Validate all authentication tokens
- Implement proper header validation
- Control write operations via explicit headers
- Default to read-only in beta
- Require explicit
enable-write: trueheader for writes - Log all write operations for audit trail
npm run clean # Remove old build artifacts
npm run build # Compile TypeScript to JavaScript- Compiled to
build/directory - Main entry:
build/index.js(executable) - Source maps included for debugging
For development and testing purposes:
# Local development mode (stdio)
TYPE_ENV=local npm run run
# Local server mode (HTTP/SSE)
TYPE_ENV=remote PORT=3000 npm run runNote: For production usage, users should connect to the hosted service at https://mcp.upsun.com/mcp rather than running their own instance.
- "Cannot find module" errors: Run
npm run build - Test failures: Check mock configurations in test files
- TypeScript errors: Verify SDK version compatibility
- Authentication failures: Check API token validity
- Use connection pooling for high-throughput scenarios
- Implement request caching for repeated operations
- Monitor memory usage with long-running processes
Key dependencies and their purposes:
@modelcontextprotocol/sdk: Core MCP functionalityupsun-sdk-node: Upsun API clientexpress: HTTP server for remote modepino: High-performance loggingzod: Runtime type validationdotenv: Environment variable loading
- Branch naming:
feature/descriptionorfix/description - Commit messages: Use conventional commits format
- Code style: Follow existing TypeScript/ESLint configuration
- Testing: All new features require tests
- Documentation: Update README.md and CLAUDE.md as needed
- Code builds without errors (
npm run build) - All tests pass (
npm test) - Linting passes (
npm run lint) - Code is formatted (
npm run prettier) - Coverage requirements met (
npm run coverage:check) - Documentation updated if needed
- For End Users: Use the hosted MCP server at https://mcp.upsun.com/mcp
- For Developers: This guide covers local development and contribution workflows
- Beta Software: Always test thoroughly in development environments
Remember: The hosted service is maintained and optimized by the Upsun team. Local development is intended for contributors and customization needs only.