Write Typescript
When to Use
Creating or modifying TypeScript MCP server projects under Forge/Configs/MCP_Servers/ or Forge/Configs/Agents/.
Two Patterns
| Pattern | Use for | Run with | Output | Committed? |
|---|---|---|---|---|
| Bundled project | MCP servers, long-running services | node dist/index.js | dist/ (gitignored) | No — rebuilt at checkout |
| Standalone script | Skill utilities, one-shot tasks | npx tsx script.ts | None | Source only |
Conventions
- Bundled projects: esbuild bundles
src/index.tstodist/index.js— a single-file ESM bundle executed withnode dist/index.js. Nonode_modulesat runtime.dist/is gitignored; rebuild with the Build Typescript skill. - Standalone scripts: Executed directly via
npx tsx script.ts. No build step, nodist/. - Module system: ESM only (
"type": "module"inpackage.json). - MCP SDK:
McpServerfrom@modelcontextprotocol/sdk/server/mcp.js,StdioServerTransportfrom@modelcontextprotocol/sdk/server/stdio.js. - Schema validation: Zod via
zod/v4import. - Project structure (bundled):
src/index.tsentry,dist/output (gitignored),package.json,tsconfig.json. - Build command (bundled):
esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js - Type checking:
tsc --noEmit(separate from build; esbuild doesn’t type-check). - Error handling: Tools return
{ content: [{ type: 'text', text: error }], isError: true }. - Logging:
console.error()for debug/diagnostic output (stdout is reserved for MCP protocol). - Naming: kebab-case for directories and file names; PascalCase for TypeScript types/interfaces.
- Railway env: Shared utility for reading
/proc/1/environto inject Railway environment variables. - No hard-coded configs: Config values like secrets, urls, etc. must never be hard-coded, but read from the environment
- No env var fallback: When using an environment variable, don’t supply a default value in case it is undefined - fail loudly instead.
- Exact versions: All dependencies and devDependencies must use exact version strings (e.g.,
"1.8.2", not"^1.8.2"). No ranges or prefixes.
tsconfig.json
package.json scripts
"build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/index.js""typecheck": "tsc --noEmit"
Dependencies
- Runtime (bundled):
@modelcontextprotocol/sdk,zod,@cfworker/json-schema(peer dep of SDK) - Dev (bundled):
esbuild,typescript,@types/node - Standalone scripts: Only Node.js built-ins; no external deps. If deps are needed, it should be a bundled project instead.
- All versions must be exact (no
^or~prefixes)