@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.
- package/dist/index.d.ts +43 -0
- package/dist/index.js +118 -0
- package/package.json +63 -0
- package/presets/.gitkeep +0 -0
- package/presets/basic/.gitignore.template +30 -0
- package/presets/basic/.lefthook.yml.template +26 -0
- package/presets/basic/package.json.template +39 -0
- package/presets/basic/src/index.ts.template +26 -0
- package/presets/basic/tsconfig.json.template +34 -0
- package/presets/cli/.gitignore.template +4 -0
- package/presets/cli/.lefthook.yml.template +26 -0
- package/presets/cli/README.md.template +35 -0
- package/presets/cli/biome.json.template +4 -0
- package/presets/cli/package.json.template +46 -0
- package/presets/cli/src/cli.ts.template +8 -0
- package/presets/cli/src/index.ts.template +7 -0
- package/presets/cli/src/program.ts.template +31 -0
- package/presets/cli/tsconfig.json.template +34 -0
- package/presets/daemon/.gitignore.template +4 -0
- package/presets/daemon/.lefthook.yml.template +26 -0
- package/presets/daemon/README.md.template +67 -0
- package/presets/daemon/biome.json.template +4 -0
- package/presets/daemon/package.json.template +49 -0
- package/presets/daemon/src/cli.ts.template +96 -0
- package/presets/daemon/src/daemon-main.ts.template +79 -0
- package/presets/daemon/src/daemon.ts.template +11 -0
- package/presets/daemon/src/index.ts.template +7 -0
- package/presets/daemon/tsconfig.json.template +23 -0
- package/presets/full-stack/.gitignore.template +30 -0
- package/presets/full-stack/README.md.template +30 -0
- package/presets/full-stack/apps/cli/package.json.template +35 -0
- package/presets/full-stack/apps/cli/src/cli.ts.template +24 -0
- package/presets/full-stack/apps/cli/src/index.test.ts.template +18 -0
- package/presets/full-stack/apps/cli/src/index.ts.template +5 -0
- package/presets/full-stack/apps/cli/tsconfig.json.template +37 -0
- package/presets/full-stack/apps/mcp/package.json.template +36 -0
- package/presets/full-stack/apps/mcp/src/index.test.ts.template +18 -0
- package/presets/full-stack/apps/mcp/src/index.ts.template +6 -0
- package/presets/full-stack/apps/mcp/src/mcp.ts.template +22 -0
- package/presets/full-stack/apps/mcp/src/server.ts.template +10 -0
- package/presets/full-stack/apps/mcp/tsconfig.json.template +37 -0
- package/presets/full-stack/package.json.template +16 -0
- package/presets/full-stack/packages/core/package.json.template +32 -0
- package/presets/full-stack/packages/core/src/handlers.ts.template +31 -0
- package/presets/full-stack/packages/core/src/index.test.ts.template +30 -0
- package/presets/full-stack/packages/core/src/index.ts.template +8 -0
- package/presets/full-stack/packages/core/src/types.ts.template +13 -0
- package/presets/full-stack/packages/core/tsconfig.json.template +34 -0
- package/presets/library/.gitignore.template +30 -0
- package/presets/library/README.md.template +29 -0
- package/presets/library/bunup.config.ts.template +20 -0
- package/presets/library/package.json.template +52 -0
- package/presets/library/src/handlers.ts.template +31 -0
- package/presets/library/src/index.test.ts.template +35 -0
- package/presets/library/src/index.ts.template +8 -0
- package/presets/library/src/types.ts.template +13 -0
- package/presets/library/tsconfig.json.template +34 -0
- package/presets/mcp/.gitignore.template +4 -0
- package/presets/mcp/.lefthook.yml.template +26 -0
- package/presets/mcp/README.md.template +54 -0
- package/presets/mcp/biome.json.template +4 -0
- package/presets/mcp/package.json.template +46 -0
- package/presets/mcp/src/index.ts.template +7 -0
- package/presets/mcp/src/mcp.ts.template +33 -0
- package/presets/mcp/src/server.ts.template +8 -0
- package/presets/mcp/tsconfig.json.template +23 -0
- package/presets/minimal/.gitignore.template +30 -0
- package/presets/minimal/.lefthook.yml.template +26 -0
- package/presets/minimal/package.json.template +46 -0
- package/presets/minimal/src/index.ts.template +26 -0
- package/presets/minimal/tsconfig.json.template +34 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}-core",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "Shared handlers for {{projectName}}",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "bun build src/index.ts --outdir dist --format=esm && tsc --emitDeclarationOnly --outDir dist",
|
|
16
|
+
"dev": "bun --watch src/index.ts",
|
|
17
|
+
"test": "bun test",
|
|
18
|
+
"test:watch": "bun test --watch",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"lint": "biome check .",
|
|
21
|
+
"lint:fix": "biome check . --write",
|
|
22
|
+
"format": "biome format --write .",
|
|
23
|
+
"clean:artifacts": "rm -rf dist .turbo"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@outfitter/contracts": "workspace:*",
|
|
27
|
+
"@outfitter/logging": "workspace:*",
|
|
28
|
+
"zod": "^4.3.5"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {},
|
|
31
|
+
"license": "MIT"
|
|
32
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Result, ValidationError, type Handler } from "@outfitter/contracts";
|
|
2
|
+
import { createLogger } from "@outfitter/logging";
|
|
3
|
+
import { greetingInputSchema, type Greeting } from "./types.js";
|
|
4
|
+
|
|
5
|
+
const logger = createLogger({ name: "{{projectName}}-core" });
|
|
6
|
+
|
|
7
|
+
export const createGreeting: Handler<unknown, Greeting, ValidationError> = async (
|
|
8
|
+
input,
|
|
9
|
+
ctx
|
|
10
|
+
) => {
|
|
11
|
+
const parsed = greetingInputSchema.safeParse(input);
|
|
12
|
+
if (!parsed.success) {
|
|
13
|
+
return Result.err(
|
|
14
|
+
new ValidationError({
|
|
15
|
+
message: "Invalid greeting input",
|
|
16
|
+
field: "name",
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const suffix = parsed.data.excited ? "!" : ".";
|
|
22
|
+
const greeting: Greeting = {
|
|
23
|
+
message: `Hello, ${parsed.data.name}${suffix}`,
|
|
24
|
+
issuedAt: new Date().toISOString(),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
logger.info(`Created greeting for ${parsed.data.name}`, {
|
|
28
|
+
requestId: ctx.requestId,
|
|
29
|
+
});
|
|
30
|
+
return Result.ok(greeting);
|
|
31
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { createContext } from "@outfitter/contracts";
|
|
3
|
+
import { createGreeting } from "./handlers.js";
|
|
4
|
+
|
|
5
|
+
describe("createGreeting", () => {
|
|
6
|
+
test("returns greeting for valid input", async () => {
|
|
7
|
+
const result = await createGreeting(
|
|
8
|
+
{ name: "Outfitter", 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, Outfitter!");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("returns validation error for invalid input", async () => {
|
|
20
|
+
const result = await createGreeting(
|
|
21
|
+
{ name: "" },
|
|
22
|
+
createContext({ cwd: process.cwd(), env: process.env })
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
expect(result.isErr()).toBe(true);
|
|
26
|
+
if (result.isErr()) {
|
|
27
|
+
expect(result.error.name).toBe("ValidationError");
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const greetingInputSchema = z.object({
|
|
4
|
+
name: z.string().min(1, "name is required"),
|
|
5
|
+
excited: z.boolean().default(false),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type GreetingInput = z.infer<typeof greetingInputSchema>;
|
|
9
|
+
|
|
10
|
+
export interface Greeting {
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly issuedAt: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"declarationMap": true,
|
|
21
|
+
"sourceMap": true,
|
|
22
|
+
"outDir": "./dist",
|
|
23
|
+
"rootDir": "./src",
|
|
24
|
+
|
|
25
|
+
"esModuleInterop": true,
|
|
26
|
+
"forceConsistentCasingInFileNames": true,
|
|
27
|
+
"isolatedModules": true,
|
|
28
|
+
"verbatimModuleSyntax": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"resolveJsonModule": true
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist"]
|
|
34
|
+
}
|
|
@@ -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,29 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
{{description}}
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add {{packageName}}
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install dependencies
|
|
15
|
+
bun install
|
|
16
|
+
|
|
17
|
+
# Build CJS + ESM artifacts
|
|
18
|
+
bun run build
|
|
19
|
+
|
|
20
|
+
# Typecheck
|
|
21
|
+
bun run typecheck
|
|
22
|
+
|
|
23
|
+
# Run tests
|
|
24
|
+
bun run test
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { defineWorkspace } from "bunup";
|
|
2
|
+
|
|
3
|
+
export default defineWorkspace(
|
|
4
|
+
[
|
|
5
|
+
{
|
|
6
|
+
name: "{{packageName}}",
|
|
7
|
+
root: ".",
|
|
8
|
+
},
|
|
9
|
+
],
|
|
10
|
+
{
|
|
11
|
+
entry: ["src/**/*.ts", "!src/**/*.test.ts", "!src/**/__tests__/**"],
|
|
12
|
+
sourceBase: "./src",
|
|
13
|
+
format: ["esm", "cjs"],
|
|
14
|
+
dts: true,
|
|
15
|
+
exports: true,
|
|
16
|
+
splitting: true,
|
|
17
|
+
clean: true,
|
|
18
|
+
target: "bun",
|
|
19
|
+
}
|
|
20
|
+
);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"sideEffects": false,
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "bunup",
|
|
22
|
+
"dev": "bun --watch src/index.ts",
|
|
23
|
+
"test": "bun test",
|
|
24
|
+
"test:watch": "bun test --watch",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"lint": "biome check .",
|
|
27
|
+
"lint:fix": "biome check . --write",
|
|
28
|
+
"format": "biome format --write .",
|
|
29
|
+
"clean:artifacts": "rm -rf dist .turbo",
|
|
30
|
+
"clean": "rm -rf dist"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@outfitter/contracts": "workspace:*",
|
|
34
|
+
"@outfitter/logging": "workspace:*",
|
|
35
|
+
"zod": "^4.3.5"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"bunup": "^0.16.29"
|
|
39
|
+
},
|
|
40
|
+
"outfitter": {
|
|
41
|
+
"template": {
|
|
42
|
+
"kind": "library",
|
|
43
|
+
"placement": "packages",
|
|
44
|
+
"surfaces": []
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"engines": {
|
|
48
|
+
"bun": ">=1.3.9"
|
|
49
|
+
},
|
|
50
|
+
"keywords": [],
|
|
51
|
+
"license": "MIT"
|
|
52
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Result, ValidationError, type Handler } from "@outfitter/contracts";
|
|
2
|
+
import { createLogger } from "@outfitter/logging";
|
|
3
|
+
import { greetingInputSchema, type Greeting } from "./types.js";
|
|
4
|
+
|
|
5
|
+
const logger = createLogger({ name: "{{projectName}}" });
|
|
6
|
+
|
|
7
|
+
export const createGreeting: Handler<unknown, Greeting, ValidationError> = async (
|
|
8
|
+
input,
|
|
9
|
+
ctx
|
|
10
|
+
) => {
|
|
11
|
+
const parsed = greetingInputSchema.safeParse(input);
|
|
12
|
+
if (!parsed.success) {
|
|
13
|
+
return Result.err(
|
|
14
|
+
new ValidationError({
|
|
15
|
+
message: "Invalid greeting input",
|
|
16
|
+
field: "name",
|
|
17
|
+
})
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const suffix = parsed.data.excited ? "!" : ".";
|
|
22
|
+
const greeting: Greeting = {
|
|
23
|
+
message: `Hello, ${parsed.data.name}${suffix}`,
|
|
24
|
+
issuedAt: new Date().toISOString(),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
logger.info(`Created greeting for ${parsed.data.name}`, {
|
|
28
|
+
requestId: ctx.requestId,
|
|
29
|
+
});
|
|
30
|
+
return Result.ok(greeting);
|
|
31
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { createContext } from "@outfitter/contracts";
|
|
3
|
+
import { createGreeting } from "./handlers.js";
|
|
4
|
+
|
|
5
|
+
describe("createGreeting", () => {
|
|
6
|
+
test("returns greeting for valid input", async () => {
|
|
7
|
+
const ctx = createContext({
|
|
8
|
+
cwd: process.cwd(),
|
|
9
|
+
env: process.env,
|
|
10
|
+
});
|
|
11
|
+
const result = await createGreeting(
|
|
12
|
+
{ name: "Outfitter", excited: true },
|
|
13
|
+
ctx
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
expect(result.isOk()).toBe(true);
|
|
17
|
+
if (result.isErr()) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
expect(result.value.message).toBe("Hello, Outfitter!");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("returns validation error for invalid input", async () => {
|
|
24
|
+
const ctx = createContext({
|
|
25
|
+
cwd: process.cwd(),
|
|
26
|
+
env: process.env,
|
|
27
|
+
});
|
|
28
|
+
const result = await createGreeting({ name: "" }, ctx);
|
|
29
|
+
|
|
30
|
+
expect(result.isErr()).toBe(true);
|
|
31
|
+
if (result.isErr()) {
|
|
32
|
+
expect(result.error.name).toBe("ValidationError");
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const greetingInputSchema = z.object({
|
|
4
|
+
name: z.string().min(1, "name is required"),
|
|
5
|
+
excited: z.boolean().default(false),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export type GreetingInput = z.infer<typeof greetingInputSchema>;
|
|
9
|
+
|
|
10
|
+
export interface Greeting {
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly issuedAt: string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noUncheckedIndexedAccess": true,
|
|
14
|
+
"exactOptionalPropertyTypes": true,
|
|
15
|
+
"noPropertyAccessFromIndexSignature": true,
|
|
16
|
+
"noImplicitReturns": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
|
|
19
|
+
"declaration": true,
|
|
20
|
+
"declarationMap": true,
|
|
21
|
+
"sourceMap": true,
|
|
22
|
+
"outDir": "./dist",
|
|
23
|
+
"rootDir": "./src",
|
|
24
|
+
|
|
25
|
+
"esModuleInterop": true,
|
|
26
|
+
"forceConsistentCasingInFileNames": true,
|
|
27
|
+
"isolatedModules": true,
|
|
28
|
+
"verbatimModuleSyntax": true,
|
|
29
|
+
"skipLibCheck": true,
|
|
30
|
+
"resolveJsonModule": true
|
|
31
|
+
},
|
|
32
|
+
"include": ["src/**/*"],
|
|
33
|
+
"exclude": ["node_modules", "dist"]
|
|
34
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Lefthook configuration
|
|
2
|
+
# https://github.com/evilmartians/lefthook
|
|
3
|
+
|
|
4
|
+
pre-commit:
|
|
5
|
+
parallel: true
|
|
6
|
+
commands:
|
|
7
|
+
format:
|
|
8
|
+
glob: "*.{js,ts,tsx,json,md}"
|
|
9
|
+
run: bunx biome format --no-errors-on-unmatched {staged_files}
|
|
10
|
+
stage_fixed: true
|
|
11
|
+
|
|
12
|
+
lint:
|
|
13
|
+
glob: "*.{js,ts,tsx}"
|
|
14
|
+
run: bunx biome lint --no-errors-on-unmatched {staged_files}
|
|
15
|
+
|
|
16
|
+
typecheck:
|
|
17
|
+
glob: "*.{ts,tsx}"
|
|
18
|
+
run: bun run typecheck
|
|
19
|
+
|
|
20
|
+
pre-push:
|
|
21
|
+
parallel: false
|
|
22
|
+
commands:
|
|
23
|
+
verify:
|
|
24
|
+
# TDD-aware strict verification with RED-phase branch carveout
|
|
25
|
+
# (*-tests, */tests, *_tests).
|
|
26
|
+
run: bunx @outfitter/tooling pre-push
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
{{description}}
|
|
4
|
+
|
|
5
|
+
MCP (Model Context Protocol) server for integration with AI assistants.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add {{packageName}}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage with Claude Desktop
|
|
14
|
+
|
|
15
|
+
Add to your Claude Desktop config:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"{{binName}}": {
|
|
21
|
+
"command": "{{binName}}"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Available Tools
|
|
28
|
+
|
|
29
|
+
### hello
|
|
30
|
+
|
|
31
|
+
Say hello to someone.
|
|
32
|
+
|
|
33
|
+
**Parameters:**
|
|
34
|
+
- `name` (string, optional): Name to greet. Default: "World"
|
|
35
|
+
|
|
36
|
+
## Development
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Install dependencies
|
|
40
|
+
bun install
|
|
41
|
+
|
|
42
|
+
# Run in development
|
|
43
|
+
bun run dev
|
|
44
|
+
|
|
45
|
+
# Build
|
|
46
|
+
bun run build
|
|
47
|
+
|
|
48
|
+
# Run tests
|
|
49
|
+
bun run test
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## License
|
|
53
|
+
|
|
54
|
+
MIT
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{packageName}}",
|
|
3
|
+
"version": "{{version}}",
|
|
4
|
+
"description": "{{description}}",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"{{binName}}": "./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
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"check": "ultracite check",
|
|
22
|
+
"verify:ci": "bun run typecheck && bun run check && bun run build && bun run test",
|
|
23
|
+
"test": "bun test",
|
|
24
|
+
"test:watch": "bun test --watch",
|
|
25
|
+
"lint": "biome check .",
|
|
26
|
+
"lint:fix": "biome check . --write",
|
|
27
|
+
"format": "biome format --write .",
|
|
28
|
+
"clean:artifacts": "rm -rf dist .turbo"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
32
|
+
"@outfitter/contracts": "workspace:*",
|
|
33
|
+
"@outfitter/types": "workspace:*",
|
|
34
|
+
"@outfitter/mcp": "workspace:*",
|
|
35
|
+
"@outfitter/logging": "workspace:*"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {},
|
|
38
|
+
"outfitter": {
|
|
39
|
+
"template": {
|
|
40
|
+
"kind": "runnable",
|
|
41
|
+
"placement": "apps",
|
|
42
|
+
"surfaces": ["mcp"]
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"license": "MIT"
|
|
46
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* {{projectName}} - MCP server definition
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Result } from "@outfitter/contracts";
|
|
6
|
+
import { createMcpServer, defineTool, connectStdio } from "@outfitter/mcp";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
|
|
9
|
+
const server = createMcpServer({
|
|
10
|
+
name: "{{binName}}",
|
|
11
|
+
version: "{{version}}",
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const helloTool = defineTool({
|
|
15
|
+
name: "hello",
|
|
16
|
+
description: "Say hello to someone",
|
|
17
|
+
inputSchema: z.object({
|
|
18
|
+
name: z.string().default("World").describe("Name to greet"),
|
|
19
|
+
}),
|
|
20
|
+
handler: async (input, ctx) => {
|
|
21
|
+
ctx.logger.info(`Greeting ${input.name}`);
|
|
22
|
+
return Result.ok({ greeting: `Hello, ${input.name}!` });
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
server.registerTool(helloTool);
|
|
27
|
+
|
|
28
|
+
export { server };
|
|
29
|
+
|
|
30
|
+
/** Start the MCP server over stdio transport. */
|
|
31
|
+
export async function startServer(): Promise<void> {
|
|
32
|
+
await connectStdio(server);
|
|
33
|
+
}
|
|
@@ -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
|