@tac0de/project-bootstrap-mcp 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=project-bootstrap-mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-bootstrap-mcp.d.ts","sourceRoot":"","sources":["../../bin/project-bootstrap-mcp.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const server_js_1 = __importDefault(require("../src/server.js"));
8
+ function parsePort(args, envPort) {
9
+ let portValue = envPort || '4000';
10
+ args.forEach((arg, index, list) => {
11
+ if (arg === '--port' && list[index + 1]) {
12
+ portValue = list[index + 1];
13
+ }
14
+ if (arg.startsWith('--port=')) {
15
+ portValue = arg.split('=')[1];
16
+ }
17
+ if (arg === '-p' && list[index + 1]) {
18
+ portValue = list[index + 1];
19
+ }
20
+ });
21
+ const parsed = Number.parseInt(portValue, 10);
22
+ if (Number.isNaN(parsed)) {
23
+ console.error(`invalid port value: ${portValue}`);
24
+ process.exit(1);
25
+ }
26
+ return parsed;
27
+ }
28
+ const port = parsePort(process.argv.slice(2), process.env.PORT);
29
+ (0, server_js_1.default)({ port });
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@tac0de/project-bootstrap-mcp",
3
+ "version": "1.1.2",
4
+ "description": "Project Bootstrap MCP API tooling for launching MCP bootstrap definitions and documentation.",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "project-bootstrap-mcp": "bin/project-bootstrap-mcp.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "npm run build && node ./bin/project-bootstrap-mcp.js",
12
+ "test": "node --test -r ts-node/register test/store.test.ts"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "bootstrap",
17
+ "api",
18
+ "cli",
19
+ "project-tools"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "author": "wonyoung choi",
25
+ "license": "MIT",
26
+ "type": "commonjs",
27
+ "engines": {
28
+ "node": ">=18"
29
+ },
30
+ "files": [
31
+ "bin",
32
+ "dist",
33
+ "src",
34
+ "test",
35
+ "LICENSE",
36
+ "README.md",
37
+ "TRD.md"
38
+ ],
39
+ "types": "dist/index.d.ts",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/tac0de/project-bootstrap-mcp"
43
+ },
44
+ "dependencies": {
45
+ "express": "^4.19.2"
46
+ },
47
+ "devDependencies": {
48
+ "@types/express": "^5.0.6",
49
+ "@types/node": "^25.0.3",
50
+ "ts-node": "^10.9.2",
51
+ "typescript": "^5.9.3"
52
+ }
53
+ }
@@ -0,0 +1,11 @@
1
+ import express from 'express';
2
+ import BootstrapStore from './store';
3
+ interface CreateAppOptions {
4
+ store?: BootstrapStore;
5
+ }
6
+ export default function createApp(options?: CreateAppOptions): {
7
+ app: express.Express;
8
+ store: BootstrapStore;
9
+ };
10
+ export {};
11
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,OAAqD,MAAM,SAAS,CAAC;AAG5E,OAAO,cAAc,MAAM,SAAS,CAAC;AAGrC,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,OAAO,GAAE,gBAAqB;;;EA8D/D"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = createApp;
7
+ const express_1 = __importDefault(require("express"));
8
+ const package_json_1 = __importDefault(require("../package.json"));
9
+ const validators_1 = require("./validators");
10
+ const store_1 = __importDefault(require("./store"));
11
+ function createApp(options = {}) {
12
+ const store = options.store ?? new store_1.default();
13
+ const app = (0, express_1.default)();
14
+ app.use(express_1.default.json());
15
+ app.get('/api/status', (_req, res) => {
16
+ res.json({
17
+ service: package_json_1.default.name,
18
+ version: package_json_1.default.version,
19
+ uptime: process.uptime(),
20
+ timestamp: new Date().toISOString(),
21
+ });
22
+ });
23
+ app.get('/api/bootstraps', (_req, res) => {
24
+ res.json({ items: store.list() });
25
+ });
26
+ app.post('/api/bootstraps', (req, res) => {
27
+ const validation = (0, validators_1.validateBootstrapPayload)(req.body);
28
+ if (!validation.valid) {
29
+ return res.status(400).json({ errors: validation.errors });
30
+ }
31
+ const payload = {
32
+ name: req.body.name,
33
+ description: req.body.description,
34
+ primaryAction: req.body.primaryAction,
35
+ targetPlatforms: Array.isArray(req.body.targetPlatforms)
36
+ ? req.body.targetPlatforms.map(String)
37
+ : [],
38
+ successCriteria: Array.isArray(req.body.successCriteria)
39
+ ? req.body.successCriteria.map(String)
40
+ : [],
41
+ steps: Array.isArray(req.body.steps)
42
+ ? req.body.steps
43
+ : [],
44
+ };
45
+ const saved = store.add(payload);
46
+ res.status(201).json(saved);
47
+ });
48
+ app.get('/api/bootstraps/:id', (req, res) => {
49
+ const record = store.find(req.params.id);
50
+ if (!record) {
51
+ return res.status(404).json({ error: 'bootstrap not found' });
52
+ }
53
+ res.json(record);
54
+ });
55
+ app.use((_req, res) => {
56
+ res.status(404).json({ error: 'not found' });
57
+ });
58
+ app.use((err, _req, res, next) => {
59
+ // eslint-disable-next-line no-console
60
+ console.error('internal error', err);
61
+ res.status(500).json({ error: 'internal server error' });
62
+ next(err);
63
+ });
64
+ return { app, store };
65
+ }
@@ -0,0 +1,5 @@
1
+ import BootstrapStore from './store';
2
+ import createApp from './app';
3
+ import startServer from './server';
4
+ export { BootstrapStore, createApp, startServer };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,SAAS,CAAC;AACrC,OAAO,SAAS,MAAM,OAAO,CAAC;AAC9B,OAAO,WAAW,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startServer = exports.createApp = exports.BootstrapStore = void 0;
7
+ const store_1 = __importDefault(require("./store"));
8
+ exports.BootstrapStore = store_1.default;
9
+ const app_1 = __importDefault(require("./app"));
10
+ exports.createApp = app_1.default;
11
+ const server_1 = __importDefault(require("./server"));
12
+ exports.startServer = server_1.default;
@@ -0,0 +1,12 @@
1
+ import type { Express } from 'express';
2
+ import type { Server } from 'http';
3
+ export interface StartServerOptions {
4
+ port?: number;
5
+ onStart?: (message: string, port: number) => void;
6
+ }
7
+ export interface StartServerResult {
8
+ app: Express;
9
+ server: Server;
10
+ }
11
+ export default function startServer({ port, onStart, }?: StartServerOptions): StartServerResult;
12
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnD;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,IAAI,EACJ,OAAO,GACR,GAAE,kBAAuB,GAAG,iBAAiB,CA0B7C"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = startServer;
7
+ const app_1 = __importDefault(require("./app"));
8
+ function startServer({ port, onStart, } = {}) {
9
+ const defaultPort = Number(process.env.PORT) || 4000;
10
+ const resolvedPort = port ?? defaultPort;
11
+ const { app } = (0, app_1.default)();
12
+ const server = app.listen(resolvedPort, () => {
13
+ const message = `Project Bootstrap MCP listening on port ${resolvedPort}`;
14
+ if (typeof onStart === 'function') {
15
+ onStart(message, resolvedPort);
16
+ }
17
+ else {
18
+ // eslint-disable-next-line no-console
19
+ console.log(message);
20
+ }
21
+ });
22
+ const graceful = () => {
23
+ server.close(() => {
24
+ // eslint-disable-next-line no-console
25
+ console.log('Project Bootstrap MCP shutting down');
26
+ process.exit(0);
27
+ });
28
+ };
29
+ process.on('SIGINT', graceful);
30
+ process.on('SIGTERM', graceful);
31
+ return { app, server };
32
+ }
@@ -0,0 +1,9 @@
1
+ import type { BootstrapPayload, BootstrapRecord } from './types';
2
+ export default class BootstrapStore {
3
+ private readonly items;
4
+ private counter;
5
+ list(): BootstrapRecord[];
6
+ add(payload: BootstrapPayload): BootstrapRecord;
7
+ find(id: string): BootstrapRecord | null;
8
+ }
9
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAEjE,MAAM,CAAC,OAAO,OAAO,cAAc;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAsC;IAC5D,OAAO,CAAC,OAAO,CAAK;IAEb,IAAI,IAAI,eAAe,EAAE;IAIzB,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe;IAW/C,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI;CAGhD"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ class BootstrapStore {
4
+ constructor() {
5
+ this.items = new Map();
6
+ this.counter = 1;
7
+ }
8
+ list() {
9
+ return Array.from(this.items.values());
10
+ }
11
+ add(payload) {
12
+ const id = String(this.counter++);
13
+ const record = {
14
+ id,
15
+ createdAt: new Date().toISOString(),
16
+ ...payload,
17
+ };
18
+ this.items.set(id, record);
19
+ return record;
20
+ }
21
+ find(id) {
22
+ return this.items.get(id) ?? null;
23
+ }
24
+ }
25
+ exports.default = BootstrapStore;
@@ -0,0 +1,17 @@
1
+ export interface BootstrapStep {
2
+ title: string;
3
+ detail: string;
4
+ }
5
+ export interface BootstrapPayload {
6
+ name: string;
7
+ description: string;
8
+ primaryAction: string;
9
+ targetPlatforms?: string[];
10
+ successCriteria?: string[];
11
+ steps: BootstrapStep[];
12
+ }
13
+ export interface BootstrapRecord extends BootstrapPayload {
14
+ id: string;
15
+ createdAt: string;
16
+ }
17
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACvD,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ export interface ValidationResult {
2
+ valid: boolean;
3
+ errors: string[];
4
+ }
5
+ export declare function validateBootstrapPayload(payload: unknown): ValidationResult;
6
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../src/validators.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,CAmC3E"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateBootstrapPayload = validateBootstrapPayload;
4
+ function validateBootstrapPayload(payload) {
5
+ const errors = [];
6
+ if (!payload || typeof payload !== 'object') {
7
+ errors.push('payload must be an object');
8
+ return { valid: false, errors };
9
+ }
10
+ const typedPayload = payload;
11
+ const { name, description, primaryAction, steps } = typedPayload;
12
+ if (!name || typeof name !== 'string') {
13
+ errors.push('name is required and must be a string');
14
+ }
15
+ if (!description || typeof description !== 'string') {
16
+ errors.push('description is required and must be a string');
17
+ }
18
+ if (!primaryAction || typeof primaryAction !== 'string') {
19
+ errors.push('primaryAction is required and must be a string');
20
+ }
21
+ if (!Array.isArray(steps) || steps.length === 0) {
22
+ errors.push('steps must be a non-empty array');
23
+ }
24
+ else {
25
+ steps.forEach((step, index) => {
26
+ const currentStep = step;
27
+ if (!currentStep || typeof currentStep.title !== 'string') {
28
+ errors.push(`steps[${index}].title is required`);
29
+ }
30
+ if (!currentStep || typeof currentStep.detail !== 'string') {
31
+ errors.push(`steps[${index}].detail is required`);
32
+ }
33
+ });
34
+ }
35
+ return { valid: errors.length === 0, errors };
36
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tac0de/project-bootstrap-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Project Bootstrap MCP API tooling for launching MCP bootstrap definitions and documentation.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/server.js DELETED
@@ -1,29 +0,0 @@
1
- const createApp = require('./app');
2
-
3
- function startServer({ port = process.env.PORT || 4000, onStart } = {}) {
4
- const { app } = createApp();
5
- const server = app.listen(port, () => {
6
- const message = `Project Bootstrap MCP listening on port ${port}`;
7
- if (typeof onStart === 'function') {
8
- onStart(message, port);
9
- } else {
10
- // eslint-disable-next-line no-console
11
- console.log(message);
12
- }
13
- });
14
-
15
- const graceful = () => {
16
- server.close(() => {
17
- // eslint-disable-next-line no-console
18
- console.log('Project Bootstrap MCP shutting down');
19
- process.exit(0);
20
- });
21
- };
22
-
23
- process.on('SIGINT', graceful);
24
- process.on('SIGTERM', graceful);
25
-
26
- return { app, server };
27
- }
28
-
29
- module.exports = startServer;