Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ tags
**/tmp
coverage/
.claude
work-done.md
125 changes: 125 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# AGENTS.md - pos-cli Development Guide

## Overview

pos-cli is a Node.js CLI tool (v22+) for deploying and managing platformOS applications. It uses ES modules, Commander.js for CLI commands, and Vitest for testing.

## Commands

### Installation & Build
```bash
npm ci # Install dependencies (clean install)
npm run build # Build GUI assets (admin, graphql, next, liquid)
```

### Testing
```bash
npm test # Run all tests
npm run test:watch # Run tests in watch mode
npm run test:unit # Run unit tests only
npm run test:integration # Run integration tests only
npm run test:coverage # Run tests with coverage report
npm run test:mcp-min # Run MCP server tests only
npx vitest run path/to/test.js # Run single test file
npx vitest run -t "test name" # Run single test by name
```

### Linting
```bash
npm run lint # Check code style (fails on warnings)
npm run lint:fix # Auto-fix linting issues
```

### Environment
Tests require `MPKIT_URL`, `MPKIT_EMAIL`, `MPKIT_TOKEN` environment variables for integration tests.

## Code Style Guidelines

### Imports & Modules
- Use ES modules (`import`/`export`) - this is an ESM package (`"type": "module"`)
- Use path aliases: `import Something from '#lib/something.js'`
- Use `import` for internal modules, `require()` only for Node.js built-ins when needed

### Formatting
- **Indentation**: 2 spaces (no tabs)
- **Quotes**: Single quotes (`'string'`), except to avoid escaping
- **Semicolons**: Required at end of statements
- **Line length**: Maximum 140 characters
- **Trailing commas**: Never use trailing commas

### Naming Conventions
- **Files**: kebab-case (`my-module.js`)
- **Classes**: PascalCase (`Gateway`, `ServerError`)
- **Variables/functions**: camelCase (`fetchSettings`, `deployStrategy`)
- **Constants**: UPPER_SNAKE_CASE for true constants, otherwise camelCase
- **Private members**: No underscore prefix convention; use closures or WeakMaps if true privacy needed

### Parameters
- **NEVER use underscore-prefixed parameters** (`_param`): Custom ESLint rule warns on usage
- Parameters starting with `_` signal "unused" - if you use it, remove the underscore
- Exception: `__dirname`, `__filename` are Node.js built-ins

### Functions
- Use arrow functions for callbacks, method shorthand for object methods
- Use async/await for all async operations (no callback-style code)
- Keep functions small and focused (single responsibility)

### Error Handling
- Use `try/catch` with async/await
- Throw `Error` objects with descriptive messages
- Use `ServerError` class from `lib/ServerError.js` for API errors
- Let errors bubble up; handle at appropriate level (CLI commands exit on error)
- Never swallow errors silently (at minimum, log them)

### Code Patterns

**Command files** (`bin/*.js`): Thin wrappers using Commander.js
- Parse arguments
- Fetch auth settings via `fetchSettings()`
- Delegate to lib/ modules

**Implementation** (`lib/`): Core business logic
- Gateway class for all API communication
- Strategy pattern for deployment (see `lib/deploy/`)
- Template processing with Mustache for module configuration

**MCP Server** (`mcp-min/`): Model Context Protocol server
- Tool definitions in modular files under feature directories
- Stdio and HTTP transports for MCP communication
- SSE streaming for real-time updates
- Partner Portal API tools for instance management

**Testing**:
- Unit tests in `test/unit/`
- Integration tests in `test/integration/`
- MCP server tests in `mcp-min/__tests__/`
- Use `describe()`, `test()`, `expect()` from Vitest
- Fixtures in `test/fixtures/`

### File Structure
```
pos-cli/
├── bin/ # CLI entry points (54 executables)
├── lib/ # Core implementation
│ ├── proxy.js # Gateway API client
│ ├── ServerError.js
│ ├── settings.js # Environment config (.pos file)
│ └── deploy/ # Deployment strategies
├── gui/ # Pre-built web apps (admin, graphql, liquid, next)
├── mcp-min/ # MCP server implementation
│ ├── tools.js # Tool definitions
│ ├── index.js # Server entry point
│ ├── stdio-server.js
│ ├── http-server.js
│ ├── sse.js # Server-sent events
│ └── portal/ # Partner Portal API tools
├── test/ # Tests and fixtures
└── scripts/ # Utility scripts
```

### Important Notes
- GUI directories contain pre-built apps - don't edit source there
- Configuration stored in `.pos` file (JSON format)
- `.posignore` uses gitignore syntax for sync/deploy exclusions
- Environment variables: `CI`, `DEBUG`, `NO_COLOR`, `CONCURRENCY` affect behavior
- When fixing bugs, add or update tests to prevent regressions
75 changes: 59 additions & 16 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,68 @@
# Contributing to platformOS Check
# Contributing Guide

## Standards
## Development Workflow

* PR should explain what the feature does, and why the change exists.
* PR should include any carrier specific documentation explaining how it works.
* Code _must_ be tested.
* Be consistent. Write clean code.
* Code should be generic and reusable.

## How to contribute
```bash
git clone <repo>
cd mcp
npm ci
npm run dev
```

1. Fork it (https://github.com/Platform-OS/pos-cli).
2. Go into the forked repository (`cd po-cli`) and link the repo: `npm unlink .; npm uninstall -g @platformOS/pos-cli; npm link; npm install`
2. Create your feature branch (`git checkout -b my-new-feature`).
3. Commit your changes (`git commit -am 'Add some feature'`).
4. Push to the branch (`git push origin my-new-feature`).
5. Create a new Pull Request.
## Adding a New Tool

## Running Tests
1. **Create `src/tools/new.tools.ts`**:
```typescript
export const myTool: Tool = {
name: 'platformos.my.tool',
description: 'Does X',
inputSchema: z.object({ foo: z.string() }),
handler: async (input) => ({ result: input.foo.toUpperCase() })
};
export const myTools = [myTool];
```

2. **Register in `src/tools/index.ts`**:
```typescript
export const allTools = [
...environmentTools,
...myTools,
// ...
];
```

3. **Add tests** `src/__tests__/my.tools.test.ts`
4. **Update** [TOOLS.md](TOOLS.md)

## Pre-commit Hooks

```bash
npm run lint
npm run test
npm run build
```

## Release Process

1. `npm version patch/minor/major`
2. `npm publish`
3. Update [CHANGELOG.md](CHANGELOG.md)

## Code Standards

- **TypeScript strict**
- **Zod for all schemas**
- **90%+ test coverage**
- **No `any` types**
- **JSDoc for complex functions**

## Testing Layers

| Type | Command | Purpose |
|------|---------|---------|
| Unit | `npm test` | Tool handlers, wrappers |
| Integration | `npm test` | Express endpoints |
| E2E | Manual | nock + real flows |

---
**Questions? Open an issue!**","path":"CONTRIBUTING.md
115 changes: 115 additions & 0 deletions DEPLOY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# DEPLOY.md - Production Deployment

## Docker

### Development

```bash
docker build -t mcp-dev .
docker run -p 3030:3030 \\
-e ADMIN_API_KEY=supersecret \\
-v $(pwd)/.pos:/app/.pos:ro \\
-v $(pwd)/mcp/clients.json:/app/clients.json:ro \\
mcp-dev npm run dev
```

### Production Dockerfile

```dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
COPY clients.json ./
EXPOSE 3030
CMD [\"npm\", \"start\"]
```

**Build & Run**
```bash
npm run build
docker build -t mcp-prod -f Dockerfile.prod .
docker run -p 3030:3030 \\
-e ADMIN_API_KEY=prod-key \\
-v /path/to/.pos:/app/.pos:ro \\
mcp-prod
```

## Environment Variables

| Var | Required | Default | Description |
|-----|----------|---------|-------------|
| `ADMIN_API_KEY` | Yes | - | Admin endpoint auth |
| `NODE_ENV` | No | `development` | Environment |
| `PORT` | No | `3030` | HTTP port |

## Production Checklist

- [ ] `npm run build`
- [ ] Set `ADMIN_API_KEY`
- [ ] Volume mount `.pos/envs/` (read-only)
- [ ] Volume mount `clients.json` (read-only)
- [ ] Firewall: port 3030
- [ ] Health check: `/health`
- [ ] PM2/ systemd supervision
- [ ] Log aggregation (stdout JSON)

## Kubernetes

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-server
spec:
replicas: 2
template:
spec:
containers:
- name: mcp
image: mcp-prod:latest
env:
- name: ADMIN_API_KEY
valueFrom:
secretKeyRef:
name: mcp-secrets
key: admin-key
volumeMounts:
- name: pos-config
mountPath: /app/.pos
readOnly: true
ports:
- containerPort: 3030
---
apiVersion: v1
kind: Secret
metadata:
name: mcp-secrets
data:
admin-key: <base64>
---
apiVersion: v1
kind: ConfigMap
metadata:
name: clients-config
data:
clients.json: |-
{ \"ai-clients\": { \"token\": \"...\" } }
```

## Reverse Proxy (nginx)

```nginx
server {
listen 80;
location / {
proxy_pass http://localhost:3030;
proxy_set_header Authorization $http_authorization;
proxy_set_header X-API-Key $admin_api_key;
}
}
```

---
**Recommended: Docker + nginx + CloudWatch Logs**","path":"DEPLOY.md
Loading
Loading