@platformos/platformos-mcp-supervisor 0.0.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.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Pure CLI argument + project-directory resolution for the bin.
3
+ *
4
+ * Kept separate from the bin entrypoint (which runs `main()` on import) so it
5
+ * can be unit-tested without booting a server.
6
+ */
7
+ export interface ParsedArgs {
8
+ projectDir?: string;
9
+ help: boolean;
10
+ }
11
+ /**
12
+ * Parse `--project <dir>` / `--project=<dir>` / `--help` / `-h` from a
13
+ * `process.argv.slice(2)`-style array. Unknown flags are tolerated so a
14
+ * forward-compatible client can pass extras without breaking the bin.
15
+ */
16
+ export declare function parseArgs(argv: ReadonlyArray<string>): ParsedArgs;
17
+ /**
18
+ * Resolve the project directory by precedence:
19
+ * 1. `--project` argument, 2. `POS_SUPERVISOR_PROJECT_DIR`, 3. cwd.
20
+ */
21
+ export declare function resolveProjectDir(args: ParsedArgs, env: NodeJS.ProcessEnv, cwd: string): string;
22
+ export declare const HELP = "platformos-mcp-supervisor \u2014 MCP stdio server exposing validate_code\n\nUsage:\n platformos-mcp-supervisor [--project <dir>]\n\nOptions:\n --project <dir> Project root to validate against\n (env: POS_SUPERVISOR_PROJECT_DIR; default: current directory)\n -h, --help Show this help\n";
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Parse `--project <dir>` / `--project=<dir>` / `--help` / `-h` from a
3
+ * `process.argv.slice(2)`-style array. Unknown flags are tolerated so a
4
+ * forward-compatible client can pass extras without breaking the bin.
5
+ */
6
+ export function parseArgs(argv) {
7
+ let projectDir;
8
+ let help = false;
9
+ for (let i = 0; i < argv.length; i++) {
10
+ const arg = argv[i];
11
+ if (arg === '--help' || arg === '-h') {
12
+ help = true;
13
+ }
14
+ else if (arg === '--project') {
15
+ projectDir = argv[i + 1];
16
+ i++;
17
+ }
18
+ else if (arg.startsWith('--project=')) {
19
+ projectDir = arg.slice('--project='.length);
20
+ }
21
+ }
22
+ return { projectDir, help };
23
+ }
24
+ /**
25
+ * Resolve the project directory by precedence:
26
+ * 1. `--project` argument, 2. `POS_SUPERVISOR_PROJECT_DIR`, 3. cwd.
27
+ */
28
+ export function resolveProjectDir(args, env, cwd) {
29
+ return args.projectDir ?? env.POS_SUPERVISOR_PROJECT_DIR ?? cwd;
30
+ }
31
+ export const HELP = `platformos-mcp-supervisor — MCP stdio server exposing validate_code
32
+
33
+ Usage:
34
+ platformos-mcp-supervisor [--project <dir>]
35
+
36
+ Options:
37
+ --project <dir> Project root to validate against
38
+ (env: POS_SUPERVISOR_PROJECT_DIR; default: current directory)
39
+ -h, --help Show this help
40
+ `;
41
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI entrypoint for the platformOS MCP supervisor.
4
+ *
5
+ * Resolves the project directory by precedence:
6
+ * 1. `--project <dir>` / `--project=<dir>` (wins)
7
+ * 2. `POS_SUPERVISOR_PROJECT_DIR` environment variable
8
+ * 3. `process.cwd()` — the directory the MCP client launched the bin from
9
+ *
10
+ * Boots `startServer` and lets Node keep the process alive: `server.connect()`
11
+ * registers the stdio transport but does not block, so the SIGINT/SIGTERM
12
+ * handlers installed inside `startServer` own the lifetime.
13
+ *
14
+ * The source lives under `src/bin/` (tsconfig `rootDir` is `src`); the build
15
+ * emits `dist/bin/platformos-mcp-supervisor.js`, which `package.json#bin`
16
+ * references. tsc preserves the shebang so the dist file is executable.
17
+ *
18
+ * Pure arg/dir resolution lives in `./args` so it can be unit-tested without
19
+ * importing this module (which boots the server on load).
20
+ */
21
+ import { createLogger } from '../logger.js';
22
+ import { startServer } from '../transport/server.js';
23
+ import { HELP, parseArgs, resolveProjectDir } from './args.js';
24
+ async function main() {
25
+ const args = parseArgs(process.argv.slice(2));
26
+ if (args.help) {
27
+ process.stderr.write(HELP);
28
+ return;
29
+ }
30
+ const log = createLogger('platformos-mcp-supervisor');
31
+ const projectDir = resolveProjectDir(args, process.env, process.cwd());
32
+ await startServer({ projectDir, log });
33
+ }
34
+ main().catch((err) => {
35
+ process.stderr.write(`fatal: ${err?.stack ?? String(err)}\n`);
36
+ process.exit(1);
37
+ });
38
+ //# sourceMappingURL=platformos-mcp-supervisor.js.map
@@ -0,0 +1,8 @@
1
+ /** Public surface of @platformos/platformos-mcp-supervisor. */
2
+ export { startServer } from './transport/server.js';
3
+ export type { ServerOptions, ServerHandle } from './transport/server.js';
4
+ export { registerValidateCode, VALIDATE_CODE_INPUT } from './transport/validate-code.js';
5
+ export type { SupervisorContext } from './transport/validate-code.js';
6
+ export { createLogger } from './logger.js';
7
+ export type { Logger } from './logger.js';
8
+ export * from './result/types.js';
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ /** Public surface of @platformos/platformos-mcp-supervisor. */
2
+ export { startServer } from './transport/server.js';
3
+ export { registerValidateCode, VALIDATE_CODE_INPUT } from './transport/validate-code.js';
4
+ export { createLogger } from './logger.js';
5
+ export * from './result/types.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,11 @@
1
+ import type { ValidateCodeDiagnostic } from '../result/types.js';
2
+ export interface RunLintParams {
3
+ /** Absolute project root the buffer is validated against. */
4
+ projectDir: string;
5
+ /** File under edit — absolute, or relative to `projectDir`. */
6
+ filePath: string;
7
+ /** In-memory buffer contents. */
8
+ content: string;
9
+ }
10
+ /** Lint the buffer and return the mapped diagnostics for the file. */
11
+ export declare function runLint(params: RunLintParams): Promise<ValidateCodeDiagnostic[]>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Lint adapter — the only I/O boundary on the request path.
3
+ *
4
+ * Lints an in-memory buffer in the context of its on-disk project via the
5
+ * check-node `lintBuffer` seam (a direct `check()` call — no LSP, no
6
+ * subprocess) and maps the structured check-common `Offense[]` into the
7
+ * agent-facing `ValidateCodeDiagnostic` shape.
8
+ *
9
+ * This is the minimal "lint only" slice: it carries detection results
10
+ * (check code, severity, message, range) straight through. Ergonomic
11
+ * enrichment (hints, confidence, fix translation, see-also) is added later in
12
+ * `enrich/`; for now diagnostics have no `fix` / `hint`, and the structured
13
+ * `Offense.fix` / `suggest` are intentionally not translated.
14
+ */
15
+ import { isAbsolute, join } from 'node:path';
16
+ import { lintBuffer, Severity } from '@platformos/platformos-check-node';
17
+ const SEVERITY = {
18
+ [Severity.ERROR]: 'error',
19
+ [Severity.WARNING]: 'warning',
20
+ [Severity.INFO]: 'info',
21
+ };
22
+ /** Lint the buffer and return the mapped diagnostics for the file. */
23
+ export async function runLint(params) {
24
+ const { projectDir, filePath, content } = params;
25
+ const absoluteFilePath = isAbsolute(filePath) ? filePath : join(projectDir, filePath);
26
+ const offenses = await lintBuffer({ root: projectDir, filePath: absoluteFilePath, content });
27
+ return offenses.map(toDiagnostic);
28
+ }
29
+ /**
30
+ * Map a check-common `Offense` to a `ValidateCodeDiagnostic`.
31
+ *
32
+ * check-common positions are 0-based for BOTH line and character
33
+ * (`getPosition` uses `line-column` with `origin: 0`); the agent surface uses
34
+ * 1-based line + 1-based column, so both get `+ 1`.
35
+ */
36
+ function toDiagnostic(offense) {
37
+ return {
38
+ check: offense.check,
39
+ severity: SEVERITY[offense.severity],
40
+ message: offense.message,
41
+ line: offense.start.line + 1,
42
+ column: offense.start.character + 1,
43
+ end_line: offense.end.line + 1,
44
+ end_column: offense.end.character + 1,
45
+ };
46
+ }
47
+ //# sourceMappingURL=lint.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * stderr-only logger.
3
+ *
4
+ * stdout is reserved for the MCP JSON-RPC stream — anything written there
5
+ * corrupts the transport. Every operational log line therefore goes to stderr.
6
+ */
7
+ export type Logger = (message: string) => void;
8
+ export declare function createLogger(prefix?: string): Logger;
package/dist/logger.js ADDED
@@ -0,0 +1,7 @@
1
+ export function createLogger(prefix) {
2
+ const tag = prefix ? ` ${prefix}` : '';
3
+ return (message) => {
4
+ process.stderr.write(`${new Date().toISOString()} [info]${tag}: ${message}\n`);
5
+ };
6
+ }
7
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Result assembly (minimal "lint only" slice).
3
+ *
4
+ * Buckets the mapped diagnostics into errors / warnings / infos and derives the
5
+ * `status` + `must_fix_before_write` envelope. PURE — no I/O, consumes only the
6
+ * diagnostic list and the shared result types.
7
+ *
8
+ * The ergonomic transforms (clustering, scorecard, the explicit
9
+ * blocking-warning set, `next_step`, tips, domain_guide, structural) are added
10
+ * in later tasks; they are left empty/null here.
11
+ */
12
+ import type { ValidateCodeDiagnostic, ValidateCodeMode, ValidateCodeResult } from './types.js';
13
+ export declare function assembleResult(diagnostics: ValidateCodeDiagnostic[], _mode: ValidateCodeMode): ValidateCodeResult;
@@ -0,0 +1,25 @@
1
+ export function assembleResult(diagnostics,
2
+ // Reserved: `full`/`quick` do not yet change output (no heavier stages exist).
3
+ _mode) {
4
+ const errors = diagnostics.filter((d) => d.severity === 'error');
5
+ const warnings = diagnostics.filter((d) => d.severity === 'warning');
6
+ const infos = diagnostics.filter((d) => d.severity === 'info');
7
+ const status = errors.length > 0 ? 'error' : warnings.length > 0 ? 'warning' : 'ok';
8
+ return {
9
+ status,
10
+ // Minimal gate: any error blocks the write. The richer blocking-warning set
11
+ // is defined in the result-assembly task.
12
+ must_fix_before_write: errors.length > 0,
13
+ errors,
14
+ warnings,
15
+ infos,
16
+ proposed_fixes: [],
17
+ clusters: [],
18
+ scorecard: [],
19
+ parse_error: null,
20
+ tips: [],
21
+ domain_guide: null,
22
+ structural: null,
23
+ };
24
+ }
25
+ //# sourceMappingURL=assemble.js.map
@@ -0,0 +1,155 @@
1
+ /**
2
+ * The `validate_code` result contract — the agent-facing surface of the
3
+ * supervisor.
4
+ *
5
+ * This is intentionally separate from check-common's `Offense`: `Offense` is a
6
+ * stable, minimal detection type consumed by editors/CLI/browser, whereas
7
+ * `ValidateCodeResult` is an LLM-ergonomics surface that may churn as agent
8
+ * behaviour is tuned. The `result/` layer assembles this shape from enriched
9
+ * diagnostics + advisories via order-independent pure transforms.
10
+ *
11
+ * Field names mirror the v1 supervisor so the parity safety net (TASK-8.5) can
12
+ * compare unchanged-contract fields against the captured baselines. Fields
13
+ * marked "TASK-8" are part of the contract but are only populated once the
14
+ * supervisor's per-domain layer and rule library are restored; the minimal
15
+ * TASK-7 build leaves them empty / null.
16
+ */
17
+ export type ValidateCodeMode = 'full' | 'quick';
18
+ export type ValidateCodeStatus = 'ok' | 'warning' | 'error';
19
+ export type ValidateCodeSeverity = 'error' | 'warning' | 'info';
20
+ /** Tool input. */
21
+ export interface ValidateCodeParams {
22
+ /** Path of the file under edit (absolute, or relative to the project root). */
23
+ file_path: string;
24
+ /** The file contents to validate (the in-memory buffer). */
25
+ content: string;
26
+ /** Depth of analysis. Defaults to `full`. */
27
+ mode?: ValidateCodeMode;
28
+ }
29
+ /**
30
+ * An agent-facing fix. Translated from a check-common `FixDescription` (the
31
+ * structured edits the engine already computed); the supervisor never
32
+ * regenerates edit text from scratch.
33
+ *
34
+ * - `text_edit` — replace `[start_index, end_index)` with `new_text`.
35
+ * - `insert` — insert `new_text` at `start_index` (`end_index === start_index`).
36
+ * - `guidance` — prose only; no machine-applicable edit.
37
+ */
38
+ export type AgentFix = {
39
+ type: 'text_edit' | 'insert';
40
+ description?: string;
41
+ /** 0-based offset into the file. */
42
+ start_index: number;
43
+ /** 0-based offset into the file. */
44
+ end_index: number;
45
+ new_text: string;
46
+ } | {
47
+ type: 'guidance';
48
+ description: string;
49
+ };
50
+ /**
51
+ * A diagnostic as surfaced to the agent. Carries the structured check-common
52
+ * fields (`check`, `severity`, range, `message`) plus the supervisor's
53
+ * ergonomic enrichment (`hint`, `suggestion`, `confidence`, `fix`, `see_also`).
54
+ * Line/column are 1-based (converted from check-common's 0-based offsets in the
55
+ * `result/` layer).
56
+ */
57
+ export interface ValidateCodeDiagnostic {
58
+ /** The check code, e.g. `MissingPartial`, or a `pos-supervisor:` advisory code. */
59
+ check: string;
60
+ severity: ValidateCodeSeverity;
61
+ message: string;
62
+ /** 1-based line of the diagnostic start. */
63
+ line: number;
64
+ /** 1-based column of the diagnostic start. */
65
+ column: number;
66
+ /** 1-based line of the diagnostic end, when known. */
67
+ end_line?: number;
68
+ /** 1-based column of the diagnostic end, when known. */
69
+ end_column?: number;
70
+ /** Markdown explanation for the agent. */
71
+ hint?: string;
72
+ /** A short, one-line "did you mean / use this" pointer. */
73
+ suggestion?: string;
74
+ /** Static confidence in [0, 1] that this diagnostic + its fix are correct. */
75
+ confidence?: number;
76
+ /** A single concrete fix for this diagnostic, when one is available. */
77
+ fix?: AgentFix;
78
+ /** A pointer to another supervisor tool / doc that helps resolve this. */
79
+ see_also?: SeeAlso;
80
+ }
81
+ export interface SeeAlso {
82
+ tool?: string;
83
+ args?: Record<string, unknown>;
84
+ reason?: string;
85
+ }
86
+ /**
87
+ * A proposed fix shown to the agent at the top level of the result. Carries the
88
+ * originating `check` so the agent can correlate it with a diagnostic.
89
+ */
90
+ export type ProposedFix = AgentFix & {
91
+ check?: string | null;
92
+ };
93
+ /** A group of related diagnostics sharing a root cause, with a unified remedy. */
94
+ export interface DiagnosticCluster {
95
+ check: string;
96
+ count: number;
97
+ unified_fix?: string;
98
+ }
99
+ /** An advisory note about the file's architecture (doc-block coverage, layout correctness, …). */
100
+ export interface ScorecardNote {
101
+ category: string;
102
+ status: 'ok' | 'warning' | 'info';
103
+ reason: string;
104
+ }
105
+ export interface TipEntry {
106
+ id: string;
107
+ severity: string;
108
+ message: string;
109
+ }
110
+ export interface DomainGuideGotcha {
111
+ id: string;
112
+ message: string;
113
+ severity: string;
114
+ applies_to_errors?: string[];
115
+ }
116
+ export interface DomainGuide {
117
+ domain: string;
118
+ rule?: string;
119
+ triggered_gotchas: DomainGuideGotcha[];
120
+ }
121
+ export interface ValidateCodeStructuralSnapshot {
122
+ renders_used: string[];
123
+ filters_used: string[];
124
+ tags_used: string[];
125
+ translation_keys: string[];
126
+ doc_params: string[];
127
+ slug: string | null;
128
+ layout: string | null;
129
+ method: string | null;
130
+ }
131
+ /**
132
+ * The full `validate_code` result. Serialized as a single JSON text block over
133
+ * the MCP stdio transport.
134
+ */
135
+ export interface ValidateCodeResult {
136
+ status: ValidateCodeStatus;
137
+ /**
138
+ * When true the agent MUST NOT write the file. Set by any error or any
139
+ * "blocking" warning (the blocking set is defined explicitly in `result/`).
140
+ */
141
+ must_fix_before_write: boolean;
142
+ errors: ValidateCodeDiagnostic[];
143
+ warnings: ValidateCodeDiagnostic[];
144
+ infos: ValidateCodeDiagnostic[];
145
+ proposed_fixes: ProposedFix[];
146
+ clusters: DiagnosticCluster[];
147
+ scorecard: ScorecardNote[];
148
+ /** Deterministic prose telling the agent what to do next. */
149
+ next_step?: string;
150
+ /** Parse-failure message when the file could not be parsed at all; null/absent otherwise. */
151
+ parse_error?: string | null;
152
+ tips?: TipEntry[];
153
+ domain_guide?: DomainGuide | null;
154
+ structural?: ValidateCodeStructuralSnapshot | null;
155
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The `validate_code` result contract — the agent-facing surface of the
3
+ * supervisor.
4
+ *
5
+ * This is intentionally separate from check-common's `Offense`: `Offense` is a
6
+ * stable, minimal detection type consumed by editors/CLI/browser, whereas
7
+ * `ValidateCodeResult` is an LLM-ergonomics surface that may churn as agent
8
+ * behaviour is tuned. The `result/` layer assembles this shape from enriched
9
+ * diagnostics + advisories via order-independent pure transforms.
10
+ *
11
+ * Field names mirror the v1 supervisor so the parity safety net (TASK-8.5) can
12
+ * compare unchanged-contract fields against the captured baselines. Fields
13
+ * marked "TASK-8" are part of the contract but are only populated once the
14
+ * supervisor's per-domain layer and rule library are restored; the minimal
15
+ * TASK-7 build leaves them empty / null.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * MCP stdio server lifecycle.
3
+ *
4
+ * `startServer` wires an `McpServer` to a `StdioServerTransport`, registers the
5
+ * `validate_code` tool, and installs SIGINT/SIGTERM handlers. It is the
6
+ * embedding surface; the bin (`bin/platformos-mcp-supervisor.ts`) is the
7
+ * user-facing surface.
8
+ */
9
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
+ import { type Logger } from '../logger.js';
11
+ import { type SupervisorContext } from './validate-code.js';
12
+ export interface ServerOptions {
13
+ /** Absolute project root that buffers are validated against. */
14
+ projectDir: string;
15
+ /** Logger sink (stderr by default). */
16
+ log?: Logger;
17
+ /** Advertised server version. */
18
+ version?: string;
19
+ }
20
+ export interface ServerHandle {
21
+ server: McpServer;
22
+ context: SupervisorContext;
23
+ /** Tear down the transport. Idempotent. */
24
+ shutdown: (reason?: string) => Promise<void>;
25
+ }
26
+ export declare function startServer(opts: ServerOptions): Promise<ServerHandle>;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * MCP stdio server lifecycle.
3
+ *
4
+ * `startServer` wires an `McpServer` to a `StdioServerTransport`, registers the
5
+ * `validate_code` tool, and installs SIGINT/SIGTERM handlers. It is the
6
+ * embedding surface; the bin (`bin/platformos-mcp-supervisor.ts`) is the
7
+ * user-facing surface.
8
+ */
9
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
10
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
+ import { createLogger } from '../logger.js';
12
+ import { registerValidateCode } from './validate-code.js';
13
+ const SERVER_NAME = 'platformos-mcp-supervisor';
14
+ const DEFAULT_VERSION = '0.0.1';
15
+ export async function startServer(opts) {
16
+ const log = opts.log ?? createLogger(SERVER_NAME);
17
+ const context = { projectDir: opts.projectDir, log };
18
+ const server = new McpServer({ name: SERVER_NAME, version: opts.version ?? DEFAULT_VERSION });
19
+ registerValidateCode(server, context);
20
+ const transport = new StdioServerTransport();
21
+ await server.connect(transport);
22
+ log(`listening on stdio (project: ${opts.projectDir})`);
23
+ let closed = false;
24
+ const shutdown = async (reason) => {
25
+ if (closed)
26
+ return;
27
+ closed = true;
28
+ if (reason)
29
+ log(`shutting down (${reason})`);
30
+ await server.close();
31
+ };
32
+ installSignalHandlers(shutdown);
33
+ return { server, context, shutdown };
34
+ }
35
+ function installSignalHandlers(shutdown) {
36
+ for (const signal of ['SIGINT', 'SIGTERM']) {
37
+ process.once(signal, () => {
38
+ void shutdown(signal).finally(() => process.exit(0));
39
+ });
40
+ }
41
+ }
42
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Registration of the `validate_code` MCP tool.
3
+ *
4
+ * Current slice: the handler runs the real lint (`check()` via the check-node
5
+ * seam) and returns the detection results mapped into `ValidateCodeResult`.
6
+ * The ergonomic stages (enrich → advise → richer result assembly) are layered
7
+ * in by later tasks; the handler shape stays the same.
8
+ */
9
+ import { type ZodRawShape } from 'zod';
10
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ import type { Logger } from '../logger.js';
12
+ /** Per-server context threaded into the handler. */
13
+ export interface SupervisorContext {
14
+ /** Absolute project root the buffer is validated against. */
15
+ projectDir: string;
16
+ log: Logger;
17
+ }
18
+ /**
19
+ * zod raw shape for the tool input (validated by the MCP SDK before dispatch).
20
+ *
21
+ * Typed as `ZodRawShape` (not the inferred literal shape) so the SDK's
22
+ * `registerTool` does not perform excessively deep type instantiation over the
23
+ * schema; the handler casts the validated args to `ValidateCodeParams`.
24
+ */
25
+ export declare const VALIDATE_CODE_INPUT: ZodRawShape;
26
+ export declare function registerValidateCode(server: McpServer, ctx: SupervisorContext): void;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Registration of the `validate_code` MCP tool.
3
+ *
4
+ * Current slice: the handler runs the real lint (`check()` via the check-node
5
+ * seam) and returns the detection results mapped into `ValidateCodeResult`.
6
+ * The ergonomic stages (enrich → advise → richer result assembly) are layered
7
+ * in by later tasks; the handler shape stays the same.
8
+ */
9
+ import { z } from 'zod';
10
+ import { runLint } from '../lint/lint.js';
11
+ import { assembleResult } from '../result/assemble.js';
12
+ /**
13
+ * zod raw shape for the tool input (validated by the MCP SDK before dispatch).
14
+ *
15
+ * Typed as `ZodRawShape` (not the inferred literal shape) so the SDK's
16
+ * `registerTool` does not perform excessively deep type instantiation over the
17
+ * schema; the handler casts the validated args to `ValidateCodeParams`.
18
+ */
19
+ export const VALIDATE_CODE_INPUT = {
20
+ file_path: z
21
+ .string()
22
+ .describe('Path of the file under edit (absolute, or relative to the project root).'),
23
+ content: z.string().describe('The file contents to validate (the in-memory buffer).'),
24
+ mode: z
25
+ .enum(['full', 'quick'])
26
+ .optional()
27
+ .describe('Analysis depth. `full` (default) runs the heavier ergonomic stages; `quick` is lint + enrichment.'),
28
+ };
29
+ const DESCRIPTION = 'Validate a platformOS Liquid/GraphQL/YAML file before writing it. Returns structured errors, ' +
30
+ 'warnings, infos, proposed fixes, and a must_fix_before_write gate.';
31
+ export function registerValidateCode(server, ctx) {
32
+ server.registerTool('validate_code', { description: DESCRIPTION, inputSchema: VALIDATE_CODE_INPUT }, async (args) => toToolResult(await runValidateCode(ctx, args)));
33
+ }
34
+ /** Lint the buffer via the check-node seam and assemble the result. */
35
+ async function runValidateCode(ctx, params) {
36
+ const mode = params.mode ?? 'full';
37
+ ctx.log(`validate_code: ${params.file_path} (${mode})`);
38
+ const diagnostics = await runLint({
39
+ projectDir: ctx.projectDir,
40
+ filePath: params.file_path,
41
+ content: params.content,
42
+ });
43
+ return assembleResult(diagnostics, mode);
44
+ }
45
+ /** Wrap a result in the MCP text-content envelope (every result is one JSON text block). */
46
+ function toToolResult(result) {
47
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
48
+ }
49
+ //# sourceMappingURL=validate-code.js.map
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@platformos/platformos-mcp-supervisor",
3
+ "version": "0.0.2",
4
+ "description": "platformOS Model Context Protocol (MCP) server exposing validate_code for LLM agents.",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ }
13
+ },
14
+ "author": "platformOS",
15
+ "homepage": "https://github.com/Platform-OS/platformos-tools/tree/master/packages/platformos-mcp-supervisor#readme",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/Platform-OS/platformos-tools.git",
19
+ "directory": "packages/platformos-mcp-supervisor"
20
+ },
21
+ "bugs": {
22
+ "url": "https://github.com/Platform-OS/platformos-tools/issues"
23
+ },
24
+ "license": "MIT",
25
+ "publishConfig": {
26
+ "access": "public",
27
+ "@platformos:registry": "https://registry.npmjs.org"
28
+ },
29
+ "bin": {
30
+ "platformos-mcp-supervisor": "dist/bin/platformos-mcp-supervisor.js"
31
+ },
32
+ "files": [
33
+ "dist/**/*.js",
34
+ "dist/**/*.d.ts",
35
+ "dist/data/**/*"
36
+ ],
37
+ "scripts": {
38
+ "build": "yarn build:ts",
39
+ "build:ci": "yarn build",
40
+ "build:ts": "tsc -b tsconfig.build.json",
41
+ "dev": "tsc --watch",
42
+ "test": "vitest",
43
+ "type-check": "tsc --noEmit"
44
+ },
45
+ "dependencies": {
46
+ "@modelcontextprotocol/sdk": "^1.29.0",
47
+ "@platformos/platformos-check-common": "0.0.20",
48
+ "@platformos/platformos-check-docs-updater": "0.0.20",
49
+ "@platformos/platformos-check-node": "0.0.20",
50
+ "@platformos/platformos-graph": "0.0.20",
51
+ "zod": "^3.23.8"
52
+ },
53
+ "devDependencies": {}
54
+ }