@outfitter/presets 0.2.0

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.
Files changed (71) hide show
  1. package/dist/index.d.ts +43 -0
  2. package/dist/index.js +118 -0
  3. package/package.json +63 -0
  4. package/presets/.gitkeep +0 -0
  5. package/presets/basic/.gitignore.template +30 -0
  6. package/presets/basic/.lefthook.yml.template +26 -0
  7. package/presets/basic/package.json.template +39 -0
  8. package/presets/basic/src/index.ts.template +26 -0
  9. package/presets/basic/tsconfig.json.template +34 -0
  10. package/presets/cli/.gitignore.template +4 -0
  11. package/presets/cli/.lefthook.yml.template +26 -0
  12. package/presets/cli/README.md.template +35 -0
  13. package/presets/cli/biome.json.template +4 -0
  14. package/presets/cli/package.json.template +46 -0
  15. package/presets/cli/src/cli.ts.template +8 -0
  16. package/presets/cli/src/index.ts.template +7 -0
  17. package/presets/cli/src/program.ts.template +31 -0
  18. package/presets/cli/tsconfig.json.template +34 -0
  19. package/presets/daemon/.gitignore.template +4 -0
  20. package/presets/daemon/.lefthook.yml.template +26 -0
  21. package/presets/daemon/README.md.template +67 -0
  22. package/presets/daemon/biome.json.template +4 -0
  23. package/presets/daemon/package.json.template +49 -0
  24. package/presets/daemon/src/cli.ts.template +96 -0
  25. package/presets/daemon/src/daemon-main.ts.template +79 -0
  26. package/presets/daemon/src/daemon.ts.template +11 -0
  27. package/presets/daemon/src/index.ts.template +7 -0
  28. package/presets/daemon/tsconfig.json.template +23 -0
  29. package/presets/full-stack/.gitignore.template +30 -0
  30. package/presets/full-stack/README.md.template +30 -0
  31. package/presets/full-stack/apps/cli/package.json.template +35 -0
  32. package/presets/full-stack/apps/cli/src/cli.ts.template +24 -0
  33. package/presets/full-stack/apps/cli/src/index.test.ts.template +18 -0
  34. package/presets/full-stack/apps/cli/src/index.ts.template +5 -0
  35. package/presets/full-stack/apps/cli/tsconfig.json.template +37 -0
  36. package/presets/full-stack/apps/mcp/package.json.template +36 -0
  37. package/presets/full-stack/apps/mcp/src/index.test.ts.template +18 -0
  38. package/presets/full-stack/apps/mcp/src/index.ts.template +6 -0
  39. package/presets/full-stack/apps/mcp/src/mcp.ts.template +22 -0
  40. package/presets/full-stack/apps/mcp/src/server.ts.template +10 -0
  41. package/presets/full-stack/apps/mcp/tsconfig.json.template +37 -0
  42. package/presets/full-stack/package.json.template +16 -0
  43. package/presets/full-stack/packages/core/package.json.template +32 -0
  44. package/presets/full-stack/packages/core/src/handlers.ts.template +31 -0
  45. package/presets/full-stack/packages/core/src/index.test.ts.template +30 -0
  46. package/presets/full-stack/packages/core/src/index.ts.template +8 -0
  47. package/presets/full-stack/packages/core/src/types.ts.template +13 -0
  48. package/presets/full-stack/packages/core/tsconfig.json.template +34 -0
  49. package/presets/library/.gitignore.template +30 -0
  50. package/presets/library/README.md.template +29 -0
  51. package/presets/library/bunup.config.ts.template +20 -0
  52. package/presets/library/package.json.template +52 -0
  53. package/presets/library/src/handlers.ts.template +31 -0
  54. package/presets/library/src/index.test.ts.template +35 -0
  55. package/presets/library/src/index.ts.template +8 -0
  56. package/presets/library/src/types.ts.template +13 -0
  57. package/presets/library/tsconfig.json.template +34 -0
  58. package/presets/mcp/.gitignore.template +4 -0
  59. package/presets/mcp/.lefthook.yml.template +26 -0
  60. package/presets/mcp/README.md.template +54 -0
  61. package/presets/mcp/biome.json.template +4 -0
  62. package/presets/mcp/package.json.template +46 -0
  63. package/presets/mcp/src/index.ts.template +7 -0
  64. package/presets/mcp/src/mcp.ts.template +33 -0
  65. package/presets/mcp/src/server.ts.template +8 -0
  66. package/presets/mcp/tsconfig.json.template +23 -0
  67. package/presets/minimal/.gitignore.template +30 -0
  68. package/presets/minimal/.lefthook.yml.template +26 -0
  69. package/presets/minimal/package.json.template +46 -0
  70. package/presets/minimal/src/index.ts.template +26 -0
  71. package/presets/minimal/tsconfig.json.template +34 -0
@@ -0,0 +1,67 @@
1
+ # {{projectName}}
2
+
3
+ {{description}}
4
+
5
+ A background daemon with CLI control interface.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ bun add {{packageName}}
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ # Start daemon in background
17
+ {{binName}} start
18
+
19
+ # Start daemon in foreground (for debugging)
20
+ {{binName}} start --foreground
21
+
22
+ # Check status
23
+ {{binName}} status
24
+
25
+ # Stop daemon
26
+ {{binName}} stop
27
+ ```
28
+
29
+ ## Endpoints
30
+
31
+ The daemon exposes a Unix socket with the following endpoints:
32
+
33
+ ### GET /health
34
+
35
+ Returns daemon health information:
36
+
37
+ ```json
38
+ {
39
+ "status": "ok",
40
+ "uptime": 12345,
41
+ "version": "{{version}}"
42
+ }
43
+ ```
44
+
45
+ ### POST /shutdown
46
+
47
+ Gracefully shuts down the daemon.
48
+
49
+ ## Development
50
+
51
+ ```bash
52
+ # Install dependencies
53
+ bun install
54
+
55
+ # Run daemon in foreground
56
+ bun run dev
57
+
58
+ # Build
59
+ bun run build
60
+
61
+ # Run tests
62
+ bun run test
63
+ ```
64
+
65
+ ## License
66
+
67
+ MIT
@@ -0,0 +1,4 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
3
+ "extends": ["ultracite/config/biome/core/biome.jsonc"]
4
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "version": "{{version}}",
4
+ "description": "{{description}}",
5
+ "type": "module",
6
+ "bin": {
7
+ "{{binName}}": "./dist/cli.js",
8
+ "{{binName}}d": "./dist/daemon.js"
9
+ },
10
+ "main": "./dist/index.js",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "scripts": {
19
+ "build": "bun build src/cli.ts src/daemon.ts --outdir dist --target bun && bun build src/index.ts --outdir dist --target bun --sourcemap",
20
+ "dev": "bun --watch src/daemon.ts -- --foreground",
21
+ "dev:daemon": "bun --watch src/daemon.ts -- --foreground",
22
+ "typecheck": "tsc --noEmit",
23
+ "check": "ultracite check",
24
+ "verify:ci": "bun run typecheck && bun run check && bun run build && bun run test",
25
+ "test": "bun test",
26
+ "test:watch": "bun test --watch",
27
+ "lint": "biome check .",
28
+ "lint:fix": "biome check . --write",
29
+ "format": "biome format --write .",
30
+ "clean:artifacts": "rm -rf dist .turbo"
31
+ },
32
+ "dependencies": {
33
+ "@outfitter/contracts": "workspace:*",
34
+ "@outfitter/types": "workspace:*",
35
+ "@outfitter/daemon": "workspace:*",
36
+ "@outfitter/cli": "workspace:*",
37
+ "@outfitter/logging": "workspace:*",
38
+ "commander": "^14.0.2"
39
+ },
40
+ "devDependencies": {},
41
+ "outfitter": {
42
+ "template": {
43
+ "kind": "runnable",
44
+ "placement": "apps",
45
+ "surfaces": ["cli", "daemon"]
46
+ }
47
+ },
48
+ "license": "MIT"
49
+ }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * {{projectName}} CLI entry point
4
+ *
5
+ * Commands: start, stop, restart, status
6
+ */
7
+
8
+ import { createCLI, command } from "@outfitter/cli";
9
+ import { createLogger } from "@outfitter/logging";
10
+ import { spawn } from "node:child_process";
11
+ import { getSocketPath, getLockPath, isDaemonAlive } from "@outfitter/daemon";
12
+
13
+ const logger = createLogger({ name: "{{binName}}" });
14
+
15
+ const TOOL_NAME = "{{binName}}";
16
+ const socketPath = getSocketPath(TOOL_NAME);
17
+ const lockPath = getLockPath(TOOL_NAME);
18
+
19
+ const program = createCLI({
20
+ name: "{{binName}}",
21
+ version: "{{version}}",
22
+ description: "{{description}}",
23
+ });
24
+
25
+ program.register(
26
+ command("start")
27
+ .description("Start the daemon")
28
+ .option("-f, --foreground", "Run in foreground")
29
+ .action(async ({ flags }) => {
30
+ const foreground = Boolean((flags as { foreground?: boolean }).foreground);
31
+
32
+ if (await isDaemonAlive(lockPath)) {
33
+ logger.warn`Daemon is already running`;
34
+ process.exit(1);
35
+ }
36
+
37
+ if (foreground) {
38
+ // Run in foreground - import and run daemon directly
39
+ const { runDaemon } = await import("./daemon-main.js");
40
+ await runDaemon();
41
+ } else {
42
+ // Spawn daemon in background
43
+ const daemon = spawn(process.execPath, [import.meta.dir + "/daemon.js"], {
44
+ detached: true,
45
+ stdio: "ignore",
46
+ });
47
+ daemon.unref();
48
+ logger.info`Daemon started with PID ${daemon.pid}`;
49
+ }
50
+ }),
51
+ );
52
+
53
+ program.register(
54
+ command("stop")
55
+ .description("Stop the daemon")
56
+ .action(async () => {
57
+ if (!(await isDaemonAlive(lockPath))) {
58
+ logger.warn`Daemon is not running`;
59
+ process.exit(1);
60
+ }
61
+ // Signal daemon to stop via HTTP
62
+ try {
63
+ const response = await fetch(`http://unix:${socketPath}:/shutdown`, {
64
+ method: "POST",
65
+ });
66
+ if (response.ok) {
67
+ logger.info`Daemon stopped`;
68
+ }
69
+ } catch {
70
+ logger.error`Failed to stop daemon`;
71
+ process.exit(1);
72
+ }
73
+ }),
74
+ );
75
+
76
+ program.register(
77
+ command("status")
78
+ .description("Check daemon status")
79
+ .action(async () => {
80
+ if (await isDaemonAlive(lockPath)) {
81
+ logger.info`Daemon is running`;
82
+ // Fetch health info
83
+ try {
84
+ const response = await fetch(`http://unix:${socketPath}:/health`);
85
+ const health = await response.json();
86
+ console.log(JSON.stringify(health, null, 2));
87
+ } catch {
88
+ logger.warn`Could not fetch health info`;
89
+ }
90
+ } else {
91
+ logger.info`Daemon is not running`;
92
+ }
93
+ }),
94
+ );
95
+
96
+ program.parse(process.argv);
@@ -0,0 +1,79 @@
1
+ /**
2
+ * {{projectName}} daemon main logic
3
+ */
4
+
5
+ import { createLogger } from "@outfitter/logging";
6
+ import {
7
+ getSocketPath,
8
+ getLockPath,
9
+ getDaemonDir,
10
+ acquireDaemonLock,
11
+ releaseDaemonLock,
12
+ } from "@outfitter/daemon";
13
+ import { mkdir } from "node:fs/promises";
14
+
15
+ const logger = createLogger({ name: "{{binName}}d" });
16
+
17
+ const TOOL_NAME = "{{binName}}";
18
+ const startTime = Date.now();
19
+
20
+ export async function runDaemon(): Promise<void> {
21
+ const socketPath = getSocketPath(TOOL_NAME);
22
+ const lockPath = getLockPath(TOOL_NAME);
23
+ const daemonDir = getDaemonDir(TOOL_NAME);
24
+
25
+ // Ensure daemon directory exists
26
+ await mkdir(daemonDir, { recursive: true });
27
+
28
+ // Acquire lock
29
+ const lockResult = await acquireDaemonLock(lockPath);
30
+ if (!lockResult.isOk()) {
31
+ logger.error`Failed to acquire lock: ${lockResult.error.message}`;
32
+ process.exit(1);
33
+ }
34
+ const lock = lockResult.value;
35
+
36
+ logger.info`Daemon starting on ${socketPath}`;
37
+
38
+ // Create HTTP server on Unix socket
39
+ const server = Bun.serve({
40
+ unix: socketPath,
41
+ fetch(request) {
42
+ const url = new URL(request.url);
43
+
44
+ if (url.pathname === "/health") {
45
+ return Response.json({
46
+ status: "ok",
47
+ uptime: Date.now() - startTime,
48
+ version: "{{version}}",
49
+ });
50
+ }
51
+
52
+ if (url.pathname === "/shutdown" && request.method === "POST") {
53
+ logger.info`Shutdown requested`;
54
+ // Schedule shutdown
55
+ setTimeout(async () => {
56
+ await releaseDaemonLock(lock);
57
+ server.stop();
58
+ process.exit(0);
59
+ }, 100);
60
+ return new Response("Shutting down");
61
+ }
62
+
63
+ return new Response("Not found", { status: 404 });
64
+ },
65
+ });
66
+
67
+ // Handle signals
68
+ const shutdown = async () => {
69
+ logger.info`Received shutdown signal`;
70
+ await releaseDaemonLock(lock);
71
+ server.stop();
72
+ process.exit(0);
73
+ };
74
+
75
+ process.on("SIGTERM", shutdown);
76
+ process.on("SIGINT", shutdown);
77
+
78
+ logger.info`Daemon running`;
79
+ }
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * {{projectName}} daemon entry point
4
+ */
5
+
6
+ import { runDaemon } from "./daemon-main.js";
7
+
8
+ runDaemon().catch((error) => {
9
+ console.error("Daemon failed:", error);
10
+ process.exit(1);
11
+ });
@@ -0,0 +1,7 @@
1
+ /**
2
+ * {{projectName}} - Public API exports
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+
7
+ export { runDaemon } from "./daemon-main.js";
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "verbatimModuleSyntax": true,
9
+ "skipLibCheck": true,
10
+ "declaration": true,
11
+ "declarationDir": "dist",
12
+ "outDir": "dist",
13
+ "rootDir": "src",
14
+ "types": ["bun-types"],
15
+ "noImplicitAny": true,
16
+ "strictNullChecks": true,
17
+ "noUncheckedIndexedAccess": true,
18
+ "exactOptionalPropertyTypes": true,
19
+ "noPropertyAccessFromIndexSignature": true
20
+ },
21
+ "include": ["src"],
22
+ "exclude": ["node_modules", "dist"]
23
+ }
@@ -0,0 +1,30 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Build output
5
+ **/dist/
6
+
7
+ # IDE
8
+ .idea/
9
+ .vscode/
10
+ *.swp
11
+ *.swo
12
+
13
+ # OS
14
+ .DS_Store
15
+ Thumbs.db
16
+
17
+ # Logs
18
+ *.log
19
+ npm-debug.log*
20
+
21
+ # Environment
22
+ .env
23
+ .env.local
24
+ .env.*.local
25
+
26
+ # Test coverage
27
+ coverage/
28
+
29
+ # Bun
30
+ bun.lockb
@@ -0,0 +1,30 @@
1
+ # {{projectName}}
2
+
3
+ {{description}}
4
+
5
+ ## Workspace Layout
6
+
7
+ ```text
8
+ {{projectName}}/
9
+ ├── apps/
10
+ │ ├── cli/ # CLI surface
11
+ │ └── mcp/ # MCP server surface
12
+ └── packages/
13
+ └── core/ # Shared handler layer
14
+ ```
15
+
16
+ ## Development
17
+
18
+ ```bash
19
+ # Install dependencies for all workspace members
20
+ bun install
21
+
22
+ # Build all packages
23
+ bun run build
24
+
25
+ # Typecheck all packages
26
+ bun run typecheck
27
+
28
+ # Run all tests
29
+ bun run test
30
+ ```
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "{{packageName}}-cli",
3
+ "version": "{{version}}",
4
+ "description": "CLI surface for {{projectName}}",
5
+ "type": "module",
6
+ "bin": {
7
+ "{{projectName}}": "./dist/cli.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "build": "bun build src/cli.ts --outdir dist --target bun && bun build src/index.ts --outdir dist --target bun --sourcemap",
19
+ "dev": "bun --watch src/cli.ts",
20
+ "test": "bun test",
21
+ "test:watch": "bun test --watch",
22
+ "typecheck": "tsc --noEmit",
23
+ "lint": "biome check .",
24
+ "lint:fix": "biome check . --write",
25
+ "format": "biome format --write .",
26
+ "clean:artifacts": "rm -rf dist .turbo"
27
+ },
28
+ "dependencies": {
29
+ "{{packageName}}-core": "workspace:*",
30
+ "@outfitter/cli": "workspace:*",
31
+ "@outfitter/contracts": "workspace:*"
32
+ },
33
+ "devDependencies": {},
34
+ "license": "MIT"
35
+ }
@@ -0,0 +1,24 @@
1
+ import { createContext } from "@outfitter/contracts";
2
+ import { output } from "@outfitter/cli";
3
+ import { createGreeting } from "{{packageName}}-core";
4
+
5
+ export async function runCli(argv: readonly string[] = process.argv): Promise<void> {
6
+ const args = argv.slice(2);
7
+ const name =
8
+ args.find((arg) => !arg.startsWith("-")) ?? "World";
9
+ const excited = args.includes("--excited");
10
+ const result = await createGreeting(
11
+ { name, excited },
12
+ createContext({ cwd: process.cwd(), env: process.env })
13
+ );
14
+
15
+ if (result.isErr()) {
16
+ throw result.error;
17
+ }
18
+
19
+ await output(result.value.message, { mode: "human" });
20
+ }
21
+
22
+ if (import.meta.main) {
23
+ await runCli();
24
+ }
@@ -0,0 +1,18 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { createContext } from "@outfitter/contracts";
3
+ import { createGreeting } from "{{packageName}}-core";
4
+
5
+ describe("cli surface", () => {
6
+ test("can use shared core handler", async () => {
7
+ const result = await createGreeting(
8
+ { name: "CLI", excited: true },
9
+ createContext({ cwd: process.cwd(), env: process.env })
10
+ );
11
+
12
+ expect(result.isOk()).toBe(true);
13
+ if (result.isErr()) {
14
+ return;
15
+ }
16
+ expect(result.value.message).toBe("Hello, CLI!");
17
+ });
18
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * {{projectName}} CLI - Public API.
3
+ */
4
+
5
+ export { runCli } from "./cli.js";
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "target": "ESNext",
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "lib": ["ESNext"],
8
+ "types": ["@types/bun"],
9
+ "baseUrl": ".",
10
+ "paths": {
11
+ "{{packageName}}-core": ["../../packages/core/src/index.ts"]
12
+ },
13
+
14
+ "strict": true,
15
+ "noImplicitAny": true,
16
+ "strictNullChecks": true,
17
+ "noUncheckedIndexedAccess": true,
18
+ "exactOptionalPropertyTypes": true,
19
+ "noPropertyAccessFromIndexSignature": true,
20
+ "noImplicitReturns": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+
23
+ "declaration": true,
24
+ "declarationMap": true,
25
+ "sourceMap": true,
26
+ "outDir": "./dist",
27
+
28
+ "esModuleInterop": true,
29
+ "forceConsistentCasingInFileNames": true,
30
+ "isolatedModules": true,
31
+ "verbatimModuleSyntax": true,
32
+ "skipLibCheck": true,
33
+ "resolveJsonModule": true
34
+ },
35
+ "include": ["src/**/*"],
36
+ "exclude": ["node_modules", "dist"]
37
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "{{packageName}}-mcp",
3
+ "version": "{{version}}",
4
+ "description": "MCP surface for {{projectName}}",
5
+ "type": "module",
6
+ "bin": {
7
+ "{{projectName}}-mcp": "./dist/server.js"
8
+ },
9
+ "main": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "build": "bun build src/server.ts --outdir dist --target bun && bun build src/index.ts --outdir dist --target bun --sourcemap",
19
+ "dev": "bun --watch src/server.ts",
20
+ "test": "bun test",
21
+ "test:watch": "bun test --watch",
22
+ "typecheck": "tsc --noEmit",
23
+ "lint": "biome check .",
24
+ "lint:fix": "biome check . --write",
25
+ "format": "biome format --write .",
26
+ "clean:artifacts": "rm -rf dist .turbo"
27
+ },
28
+ "dependencies": {
29
+ "{{packageName}}-core": "workspace:*",
30
+ "@outfitter/contracts": "workspace:*",
31
+ "@outfitter/mcp": "workspace:*",
32
+ "zod": "^4.3.5"
33
+ },
34
+ "devDependencies": {},
35
+ "license": "MIT"
36
+ }
@@ -0,0 +1,18 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { createContext } from "@outfitter/contracts";
3
+ import { createGreeting } from "{{packageName}}-core";
4
+
5
+ describe("mcp surface", () => {
6
+ test("can use shared core handler", async () => {
7
+ const result = await createGreeting(
8
+ { name: "MCP" },
9
+ createContext({ cwd: process.cwd(), env: process.env })
10
+ );
11
+
12
+ expect(result.isOk()).toBe(true);
13
+ if (result.isErr()) {
14
+ return;
15
+ }
16
+ expect(result.value.message).toBe("Hello, MCP.");
17
+ });
18
+ });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * {{projectName}} MCP - Public API.
3
+ */
4
+
5
+ export { server } from "./mcp.js";
6
+ export { startServer } from "./server.js";
@@ -0,0 +1,22 @@
1
+ import { createGreeting } from "{{packageName}}-core";
2
+ import { createMcpServer, defineTool } from "@outfitter/mcp";
3
+ import { z } from "zod";
4
+
5
+ const server = createMcpServer({
6
+ name: "{{projectName}}-mcp",
7
+ version: "{{version}}",
8
+ });
9
+
10
+ const greetTool = defineTool({
11
+ name: "greet",
12
+ description: "Generate greeting via shared core handler",
13
+ inputSchema: z.object({
14
+ name: z.string().default("World").describe("Name to greet"),
15
+ excited: z.boolean().default(false),
16
+ }),
17
+ handler: async (input, ctx) => createGreeting(input, ctx),
18
+ });
19
+
20
+ server.registerTool(greetTool);
21
+
22
+ export { server };
@@ -0,0 +1,10 @@
1
+ import { connectStdio } from "@outfitter/mcp";
2
+ import { server } from "./mcp.js";
3
+
4
+ export async function startServer(): Promise<void> {
5
+ await connectStdio(server);
6
+ }
7
+
8
+ if (import.meta.main) {
9
+ await startServer();
10
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/tsconfig",
3
+ "compilerOptions": {
4
+ "target": "ESNext",
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "lib": ["ESNext"],
8
+ "types": ["@types/bun"],
9
+ "baseUrl": ".",
10
+ "paths": {
11
+ "{{packageName}}-core": ["../../packages/core/src/index.ts"]
12
+ },
13
+
14
+ "strict": true,
15
+ "noImplicitAny": true,
16
+ "strictNullChecks": true,
17
+ "noUncheckedIndexedAccess": true,
18
+ "exactOptionalPropertyTypes": true,
19
+ "noPropertyAccessFromIndexSignature": true,
20
+ "noImplicitReturns": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+
23
+ "declaration": true,
24
+ "declarationMap": true,
25
+ "sourceMap": true,
26
+ "outDir": "./dist",
27
+
28
+ "esModuleInterop": true,
29
+ "forceConsistentCasingInFileNames": true,
30
+ "isolatedModules": true,
31
+ "verbatimModuleSyntax": true,
32
+ "skipLibCheck": true,
33
+ "resolveJsonModule": true
34
+ },
35
+ "include": ["src/**/*"],
36
+ "exclude": ["node_modules", "dist"]
37
+ }
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "private": true,
4
+ "version": "{{version}}",
5
+ "type": "module",
6
+ "workspaces": ["apps/*", "packages/*"],
7
+ "scripts": {
8
+ "build": "bun run --filter '*' build",
9
+ "dev": "bun run --filter '*' dev",
10
+ "test": "bun run --filter '*' test",
11
+ "typecheck": "bun run --filter '*' typecheck",
12
+ "lint": "bun run --filter '*' lint",
13
+ "lint:fix": "bun run --filter '*' lint:fix",
14
+ "format": "bun run --filter '*' format"
15
+ }
16
+ }