@michaelbel/cuckcoder-mcp 1.6.11
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/assets/rules/architecture.md +15 -0
- package/assets/rules/bottom-sheet.md +20 -0
- package/assets/rules/compose-color.md +22 -0
- package/assets/rules/compose-constraintlayout.md +18 -0
- package/assets/rules/compose-screen.md +33 -0
- package/assets/rules/compose-spacing.md +39 -0
- package/assets/rules/compose.md +54 -0
- package/assets/rules/dialog.md +33 -0
- package/assets/rules/domain.md +36 -0
- package/assets/rules/filesystem.md +3 -0
- package/assets/rules/git.md +11 -0
- package/assets/rules/github-readme.md +97 -0
- package/assets/rules/github-repo.md +65 -0
- package/assets/rules/kmp.md +14 -0
- package/assets/rules/kotlin.md +48 -0
- package/assets/rules/lazylist.md +36 -0
- package/assets/rules/mvi-error-handling.md +19 -0
- package/assets/rules/mvi-state.md +31 -0
- package/assets/rules/mvi.md +39 -0
- package/assets/rules/navigation.md +20 -0
- package/assets/rules/network.md +36 -0
- package/assets/rules/preview.md +31 -0
- package/assets/rules/realtime.md +39 -0
- package/assets/rules/resource.md +18 -0
- package/assets/rules/room.md +33 -0
- package/assets/rules/scaffold.md +25 -0
- package/assets/rules/shimmer.md +34 -0
- package/assets/rules/textfield.md +31 -0
- package/assets/rules/typography.md +32 -0
- package/assets/rules/usecase.md +60 -0
- package/assets/rules/workflow.md +17 -0
- package/assets/rules/workmanager.md +44 -0
- package/assets/skills/create-data-layer/SKILL.md +60 -0
- package/assets/skills/create-datastore-preference/SKILL.md +80 -0
- package/assets/skills/create-domain-mapper/SKILL.md +30 -0
- package/assets/skills/create-feature-alert-dialog/SKILL.md +549 -0
- package/assets/skills/create-feature-bottom-sheet/SKILL.md +300 -0
- package/assets/skills/create-feature-scaffold-screen/SKILL.md +74 -0
- package/assets/skills/create-feature-scaffold-screen/references/form-screen.md +20 -0
- package/assets/skills/create-feature-scaffold-screen/references/network-only-screen.md +20 -0
- package/assets/skills/create-feature-scaffold-screen/references/paginated-screen.md +29 -0
- package/assets/skills/create-feature-scaffold-screen/references/room-backed-screen.md +23 -0
- package/assets/skills/create-feature-scaffold-screen/references/static-screen.md +13 -0
- package/assets/skills/create-guide/SKILL.md +169 -0
- package/assets/skills/create-guide/references/android-project.md +120 -0
- package/assets/skills/create-guide/references/androidx.md +49 -0
- package/assets/skills/create-guide/references/existing-guides.yaml +60 -0
- package/assets/skills/create-guide/references/github.md +71 -0
- package/assets/skills/create-guide/references/guide-defaults.yaml +51 -0
- package/assets/skills/create-guide/references/notion.md +121 -0
- package/assets/skills/create-guide/references/output-contract.md +79 -0
- package/assets/skills/create-guide/references/research.md +64 -0
- package/assets/skills/create-guide/references/validation.md +59 -0
- package/assets/skills/create-guide/scripts/validate_guide.py +167 -0
- package/assets/skills/create-guide/templates/guide-manifest.yaml +67 -0
- package/assets/skills/create-guide/templates/implementation-plan.md +30 -0
- package/assets/skills/create-guide/templates/notion-page.md +46 -0
- package/assets/skills/create-guide/templates/repository/AGENTS.md +7 -0
- package/assets/skills/create-guide/templates/repository/README.md +32 -0
- package/assets/skills/create-guide/templates/repository/SOURCES.md +32 -0
- package/assets/skills/create-guide/templates/validation-report.md +30 -0
- package/assets/skills/create-guide/tests/test_validate_guide.py +97 -0
- package/assets/skills/create-ktor-endpoint/SKILL.md +33 -0
- package/assets/skills/create-notification-flow/SKILL.md +103 -0
- package/assets/skills/create-offline-outbox/SKILL.md +110 -0
- package/assets/skills/create-paging-flow/SKILL.md +96 -0
- package/assets/skills/create-project-from-template/SKILL.md +91 -0
- package/assets/skills/create-project-from-template/assets/icons/android.svg +12 -0
- package/assets/skills/create-project-from-template/assets/icons/compose.svg +34 -0
- package/assets/skills/create-project-from-template/assets/icons/jetpack.svg +10 -0
- package/assets/skills/create-project-from-template/references/myapplication-checklist.md +92 -0
- package/assets/skills/create-room-storage/SKILL.md +39 -0
- package/assets/skills/create-shared-component/SKILL.md +160 -0
- package/assets/skills/create-signalr-channel/SKILL.md +39 -0
- package/assets/skills/create-usecase/SKILL.md +142 -0
- package/assets/skills/create-workmanager-task/SKILL.md +41 -0
- package/assets/skills/github-repo-settings/SKILL.md +152 -0
- package/assets/skills/interview-me/SKILL.md +150 -0
- package/dist/errors.js +49 -0
- package/dist/frontmatter.js +44 -0
- package/dist/github.js +23 -0
- package/dist/index.js +6 -0
- package/dist/server.js +131 -0
- package/dist/source/bundled.js +78 -0
- package/dist/source/cache.js +61 -0
- package/dist/source/github-source.js +68 -0
- package/dist/source/github.js +185 -0
- package/dist/source/index.js +36 -0
- package/dist/source/types.js +1 -0
- package/dist/validation.js +33 -0
- package/dist/version.js +26 -0
- package/package.json +38 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { getServerName, getServerVersion } from "../version.js";
|
|
2
|
+
import { WorkflowError } from "../errors.js";
|
|
3
|
+
import { BoundedTtlCache, RequestDeduplicator } from "./cache.js";
|
|
4
|
+
const BASE_RAW = "https://raw.githubusercontent.com";
|
|
5
|
+
const BASE_API = "https://api.github.com";
|
|
6
|
+
/** Per-request timeout. */
|
|
7
|
+
export const GITHUB_TIMEOUT_MS = 10_000;
|
|
8
|
+
/** Total attempts (1 initial + up to 2 retries). */
|
|
9
|
+
export const GITHUB_MAX_ATTEMPTS = 3;
|
|
10
|
+
/** Base delay for exponential backoff between retries, when the server gives no Retry-After. */
|
|
11
|
+
export const GITHUB_RETRY_BASE_DELAY_MS = 300;
|
|
12
|
+
/** Cap on a `git/trees` API response body. */
|
|
13
|
+
export const GITHUB_TREE_MAX_BYTES = 5 * 1024 * 1024;
|
|
14
|
+
/** Cap on a single raw markdown file body. */
|
|
15
|
+
export const GITHUB_FILE_MAX_BYTES = 1 * 1024 * 1024;
|
|
16
|
+
/** How long a successful response is considered fresh. */
|
|
17
|
+
export const GITHUB_CACHE_TTL_MS = 10 * 60 * 1000;
|
|
18
|
+
/** Bounded cache size (per cache instance), oldest entry evicted once exceeded. */
|
|
19
|
+
export const GITHUB_CACHE_MAX_ENTRIES = 200;
|
|
20
|
+
function delay(ms) {
|
|
21
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
22
|
+
}
|
|
23
|
+
function parseRetryAfterMs(res) {
|
|
24
|
+
const header = res.headers.get("retry-after");
|
|
25
|
+
if (!header) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
const seconds = Number(header);
|
|
29
|
+
if (Number.isFinite(seconds) && seconds >= 0) {
|
|
30
|
+
return seconds * 1000;
|
|
31
|
+
}
|
|
32
|
+
const dateMs = Date.parse(header);
|
|
33
|
+
if (!Number.isNaN(dateMs)) {
|
|
34
|
+
return Math.max(0, dateMs - Date.now());
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Hardened GitHub HTTP client for the optional remote source mode: bounded timeout, bounded
|
|
40
|
+
* retry (only for transport errors, 429, and 5xx — never for a plain 4xx like 404/403), honors
|
|
41
|
+
* `Retry-After`, caps response size, and never logs the token (it only ever goes into the
|
|
42
|
+
* `Authorization` header of the outgoing request).
|
|
43
|
+
*/
|
|
44
|
+
export class GithubClient {
|
|
45
|
+
options;
|
|
46
|
+
fetchImpl;
|
|
47
|
+
timeoutMs;
|
|
48
|
+
maxAttempts;
|
|
49
|
+
treeMaxBytes;
|
|
50
|
+
fileMaxBytes;
|
|
51
|
+
fileCache;
|
|
52
|
+
treeCache;
|
|
53
|
+
fileDedup = new RequestDeduplicator();
|
|
54
|
+
treeDedup = new RequestDeduplicator();
|
|
55
|
+
constructor(options) {
|
|
56
|
+
this.options = options;
|
|
57
|
+
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
58
|
+
this.timeoutMs = options.timeoutMs ?? GITHUB_TIMEOUT_MS;
|
|
59
|
+
this.maxAttempts = options.maxAttempts ?? GITHUB_MAX_ATTEMPTS;
|
|
60
|
+
this.treeMaxBytes = options.treeMaxBytes ?? GITHUB_TREE_MAX_BYTES;
|
|
61
|
+
this.fileMaxBytes = options.fileMaxBytes ?? GITHUB_FILE_MAX_BYTES;
|
|
62
|
+
const ttlMs = options.cacheTtlMs ?? GITHUB_CACHE_TTL_MS;
|
|
63
|
+
const maxEntries = options.cacheMaxEntries ?? GITHUB_CACHE_MAX_ENTRIES;
|
|
64
|
+
this.fileCache = new BoundedTtlCache({ ttlMs, maxEntries });
|
|
65
|
+
this.treeCache = new BoundedTtlCache({ ttlMs, maxEntries });
|
|
66
|
+
}
|
|
67
|
+
authHeaders() {
|
|
68
|
+
const headers = {
|
|
69
|
+
"User-Agent": `${getServerName()}/${getServerVersion()}`,
|
|
70
|
+
Accept: "application/vnd.github+json",
|
|
71
|
+
};
|
|
72
|
+
if (this.options.token) {
|
|
73
|
+
headers.Authorization = `Bearer ${this.options.token}`;
|
|
74
|
+
}
|
|
75
|
+
return headers;
|
|
76
|
+
}
|
|
77
|
+
async requestText(url, headers, maxBytes) {
|
|
78
|
+
let lastError;
|
|
79
|
+
for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
|
|
80
|
+
const controller = new AbortController();
|
|
81
|
+
const timeoutHandle = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
82
|
+
try {
|
|
83
|
+
const res = await this.fetchImpl(url, { headers, signal: controller.signal });
|
|
84
|
+
clearTimeout(timeoutHandle);
|
|
85
|
+
if (res.status === 404) {
|
|
86
|
+
throw new WorkflowError("NOT_FOUND", `GitHub resource not found (HTTP 404).`, { retryable: false });
|
|
87
|
+
}
|
|
88
|
+
if (res.status === 429) {
|
|
89
|
+
if (attempt < this.maxAttempts) {
|
|
90
|
+
await delay(parseRetryAfterMs(res) ?? GITHUB_RETRY_BASE_DELAY_MS * attempt);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
throw new WorkflowError("GITHUB_RATE_LIMITED", "GitHub API rate limit exceeded.", { retryable: true });
|
|
94
|
+
}
|
|
95
|
+
if (res.status >= 500 && res.status < 600) {
|
|
96
|
+
if (attempt < this.maxAttempts) {
|
|
97
|
+
await delay(parseRetryAfterMs(res) ?? GITHUB_RETRY_BASE_DELAY_MS * attempt);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
throw new WorkflowError("GITHUB_UNREACHABLE", `GitHub API returned HTTP ${res.status}.`, {
|
|
101
|
+
retryable: true,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (!res.ok) {
|
|
105
|
+
// A definitive, non-retryable 4xx (401/403/etc). Retrying with the same request will
|
|
106
|
+
// not succeed, so this is not retryable even though the code is GITHUB_UNREACHABLE.
|
|
107
|
+
throw new WorkflowError("GITHUB_UNREACHABLE", `GitHub API returned HTTP ${res.status}.`, {
|
|
108
|
+
retryable: false,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
const text = await res.text();
|
|
112
|
+
if (Buffer.byteLength(text, "utf8") > maxBytes) {
|
|
113
|
+
throw new WorkflowError("RESPONSE_TOO_LARGE", `GitHub response exceeded the ${maxBytes}-byte limit.`, {
|
|
114
|
+
retryable: false,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
return text;
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
clearTimeout(timeoutHandle);
|
|
121
|
+
if (error instanceof WorkflowError) {
|
|
122
|
+
if (!error.retryable || attempt >= this.maxAttempts) {
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
lastError = error;
|
|
126
|
+
await delay(GITHUB_RETRY_BASE_DELAY_MS * attempt);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const isAbort = error instanceof Error && error.name === "AbortError";
|
|
130
|
+
lastError = new WorkflowError(isAbort ? "GITHUB_TIMEOUT" : "GITHUB_UNREACHABLE", isAbort ? "GitHub request timed out." : `GitHub request failed: ${error instanceof Error ? error.message : String(error)}`, { retryable: true });
|
|
131
|
+
if (attempt >= this.maxAttempts) {
|
|
132
|
+
throw lastError;
|
|
133
|
+
}
|
|
134
|
+
await delay(GITHUB_RETRY_BASE_DELAY_MS * attempt);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
throw lastError instanceof Error ? lastError : new WorkflowError("GITHUB_UNREACHABLE", "GitHub request failed.");
|
|
138
|
+
}
|
|
139
|
+
async fetchFile(ref, path) {
|
|
140
|
+
const cacheKey = `${ref}:${path}`;
|
|
141
|
+
const cached = this.fileCache.get(cacheKey);
|
|
142
|
+
if (cached !== undefined) {
|
|
143
|
+
return cached;
|
|
144
|
+
}
|
|
145
|
+
return this.fileDedup.run(cacheKey, async () => {
|
|
146
|
+
const url = `${BASE_RAW}/${this.options.owner}/${this.options.repo}/${ref}/${path}`;
|
|
147
|
+
try {
|
|
148
|
+
const text = await this.requestText(url, this.authHeaders(), this.fileMaxBytes);
|
|
149
|
+
this.fileCache.set(cacheKey, text);
|
|
150
|
+
return text;
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
const stale = this.fileCache.getStale(cacheKey);
|
|
154
|
+
if (stale !== undefined && error instanceof WorkflowError && error.code !== "NOT_FOUND") {
|
|
155
|
+
return stale;
|
|
156
|
+
}
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async listTree(ref) {
|
|
162
|
+
const cacheKey = ref;
|
|
163
|
+
const cached = this.treeCache.get(cacheKey);
|
|
164
|
+
if (cached !== undefined) {
|
|
165
|
+
return cached;
|
|
166
|
+
}
|
|
167
|
+
return this.treeDedup.run(cacheKey, async () => {
|
|
168
|
+
const url = `${BASE_API}/repos/${this.options.owner}/${this.options.repo}/git/trees/${ref}?recursive=1`;
|
|
169
|
+
try {
|
|
170
|
+
const text = await this.requestText(url, this.authHeaders(), this.treeMaxBytes);
|
|
171
|
+
const data = JSON.parse(text);
|
|
172
|
+
const tree = data.tree ?? [];
|
|
173
|
+
this.treeCache.set(cacheKey, tree);
|
|
174
|
+
return tree;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
const stale = this.treeCache.getStale(cacheKey);
|
|
178
|
+
if (stale !== undefined && error instanceof WorkflowError && error.code !== "NOT_FOUND") {
|
|
179
|
+
return stale;
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { WorkflowError } from "../errors.js";
|
|
2
|
+
import { getServerVersion } from "../version.js";
|
|
3
|
+
import { BundledSource } from "./bundled.js";
|
|
4
|
+
import { GithubSource } from "./github-source.js";
|
|
5
|
+
export { BundledSource } from "./bundled.js";
|
|
6
|
+
export { GithubSource } from "./github-source.js";
|
|
7
|
+
/** `mcp-v1.2.3` — an immutable release tag, never `main`/`master`. */
|
|
8
|
+
const TAG_REF_PATTERN = /^mcp-v\d+\.\d+\.\d+$/;
|
|
9
|
+
/** A full 40-hex-character commit SHA. */
|
|
10
|
+
const SHA_REF_PATTERN = /^[0-9a-f]{40}$/;
|
|
11
|
+
export function defaultGithubRef() {
|
|
12
|
+
return `mcp-v${getServerVersion()}`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Validates a ref intended for the optional GitHub source mode. Only an immutable release tag
|
|
16
|
+
* (`mcp-v<semver>`) or a full commit SHA is accepted — `main`, `master`, short SHAs, branch
|
|
17
|
+
* names, and anything else are rejected so the server can never be pointed at a moving target.
|
|
18
|
+
*/
|
|
19
|
+
export function validateGithubRef(ref) {
|
|
20
|
+
if (TAG_REF_PATTERN.test(ref) || SHA_REF_PATTERN.test(ref)) {
|
|
21
|
+
return ref;
|
|
22
|
+
}
|
|
23
|
+
throw new WorkflowError("INVALID_SOURCE_REF", `Invalid AI_WORKFLOW_GITHUB_REF '${ref}'. Expected an immutable tag like 'mcp-v1.2.3' or a full 40-character commit SHA.`);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Picks the WorkflowSource implementation from environment variables. Bundled (no network) is
|
|
27
|
+
* the default; GitHub mode is opt-in via `AI_WORKFLOW_SOURCE=github` and always resolves to a
|
|
28
|
+
* validated immutable ref, never the mutable `main` branch.
|
|
29
|
+
*/
|
|
30
|
+
export function createSource(env, fetchImpl) {
|
|
31
|
+
if (env.AI_WORKFLOW_SOURCE === "github") {
|
|
32
|
+
const ref = validateGithubRef(env.AI_WORKFLOW_GITHUB_REF ?? defaultGithubRef());
|
|
33
|
+
return new GithubSource(ref, env.GITHUB_TOKEN, fetchImpl);
|
|
34
|
+
}
|
|
35
|
+
return new BundledSource(defaultGithubRef());
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { WorkflowError } from "./errors.js";
|
|
2
|
+
const DEPRECATED_SKILL_SUFFIX = "/SKILL";
|
|
3
|
+
/**
|
|
4
|
+
* Pure kebab-case skill directory name: lowercase alphanumeric segments separated by `-`.
|
|
5
|
+
* No slash, dot, backslash, underscore, uppercase letter, or whitespace can appear, which is
|
|
6
|
+
* sufficient to make path traversal (`..`, `/`, absolute paths) impossible.
|
|
7
|
+
*/
|
|
8
|
+
const SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
9
|
+
/**
|
|
10
|
+
* Rule name: the lowercase kebab-case basename without `.md`, e.g. `mvi-error-handling`.
|
|
11
|
+
* Slashes, dots, backslashes, underscores and uppercase letters cannot match, so path traversal
|
|
12
|
+
* is impossible.
|
|
13
|
+
*/
|
|
14
|
+
const RULE_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15
|
+
/**
|
|
16
|
+
* Validates a skill name from an MCP caller. Accepts the deprecated `<name>/SKILL` alias (stripped
|
|
17
|
+
* before validation) for backward compatibility, but the returned value is always the bare name.
|
|
18
|
+
*/
|
|
19
|
+
export function validateSkillName(rawName) {
|
|
20
|
+
const name = rawName.endsWith(DEPRECATED_SKILL_SUFFIX)
|
|
21
|
+
? rawName.slice(0, -DEPRECATED_SKILL_SUFFIX.length)
|
|
22
|
+
: rawName;
|
|
23
|
+
if (!SKILL_NAME_PATTERN.test(name)) {
|
|
24
|
+
throw new WorkflowError("INVALID_NAME", `Invalid skill name '${rawName}'. Expected a kebab-case skill directory name, e.g. 'create-feature-scaffold-screen'.`);
|
|
25
|
+
}
|
|
26
|
+
return name;
|
|
27
|
+
}
|
|
28
|
+
export function validateRuleName(rawName) {
|
|
29
|
+
if (!RULE_NAME_PATTERN.test(rawName)) {
|
|
30
|
+
throw new WorkflowError("INVALID_NAME", `Invalid rule name '${rawName}'. Expected a lowercase kebab-case rule name, e.g. 'mvi-error-handling'.`);
|
|
31
|
+
}
|
|
32
|
+
return rawName;
|
|
33
|
+
}
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
let cachedPackageJson;
|
|
5
|
+
/**
|
|
6
|
+
* Resolves mcp/package.json relative to the currently running module file. This works
|
|
7
|
+
* identically whether the module is executing as `src/version.ts` (via tsx, one directory below
|
|
8
|
+
* mcp/) or as the compiled `dist/version.js` (also one directory below mcp/) — so there is a
|
|
9
|
+
* single source of truth for the package version and no separate literal to keep in sync.
|
|
10
|
+
*/
|
|
11
|
+
export function readPackageJson() {
|
|
12
|
+
if (cachedPackageJson) {
|
|
13
|
+
return cachedPackageJson;
|
|
14
|
+
}
|
|
15
|
+
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const packageJsonPath = join(moduleDir, "..", "package.json");
|
|
17
|
+
const raw = readFileSync(packageJsonPath, "utf8");
|
|
18
|
+
cachedPackageJson = JSON.parse(raw);
|
|
19
|
+
return cachedPackageJson;
|
|
20
|
+
}
|
|
21
|
+
export function getServerVersion() {
|
|
22
|
+
return readPackageJson().version;
|
|
23
|
+
}
|
|
24
|
+
export function getServerName() {
|
|
25
|
+
return readPackageJson().name;
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@michaelbel/cuckcoder-mcp",
|
|
3
|
+
"version": "1.6.11",
|
|
4
|
+
"description": "MCP server for Cuckcoder rules and skills",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"cuckcoder-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"copy-assets": "tsx scripts/copy-assets.ts",
|
|
12
|
+
"build": "npm run copy-assets && tsc",
|
|
13
|
+
"dev": "npm run copy-assets && tsx src/index.ts",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"test": "npm run copy-assets && tsx --test \"test/**/*.test.ts\"",
|
|
16
|
+
"validate": "tsx scripts/validate.ts",
|
|
17
|
+
"smoke": "tsx scripts/smoke.ts",
|
|
18
|
+
"check": "npm run validate && npm test && npm run build && npm run smoke && npm pack --dry-run",
|
|
19
|
+
"prepack": "npm run build",
|
|
20
|
+
"prepare": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist/",
|
|
24
|
+
"assets/"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
31
|
+
"zod": "^3.22.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^20.0.0",
|
|
35
|
+
"tsx": "^4.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|