sphior-code-mcp 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SPHIOR Security
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # sphior-code-mcp
2
+
3
+ Official **Model Context Protocol (MCP)** server for **SPHIOR CODE** — surface security findings from your GitHub repositories directly inside any MCP-compatible AI coding assistant.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/sphior-code-mcp.svg)](https://www.npmjs.com/package/sphior-code-mcp)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+
8
+ ## What this gives you
9
+
10
+ Your AI assistant can now answer questions like:
11
+
12
+ - *"What are the highest-severity vulnerabilities in my code right now?"*
13
+ - *"Show me the fix for finding `abc-123`."*
14
+ - *"Mark this SQL injection alert as resolved — I just fixed it."*
15
+ - *"What's our overall security posture this month?"*
16
+
17
+ …using **live data from SPHIOR CODE's scanning engine** (AI SAST + SCA powered by OSV.dev).
18
+
19
+ ## Supported clients
20
+
21
+ This is a standard MCP stdio server, so it works with **any MCP-compatible client**:
22
+
23
+ | Client | Config location | Setup |
24
+ |---|---|---|
25
+ | **Cursor** | `~/.cursor/mcp.json` | [Add MCP](https://cursor.sh/) |
26
+ | **Claude Code** | `~/.claude.json` | `claude mcp add sphior-code -- npx sphior-code-mcp` |
27
+ | **VS Code** | `~/.config/Code/User/settings.json` (`mcp.servers`) | Built-in MCP |
28
+ | **GitHub Copilot (VS Code)** | `.vscode/mcp.json` | Native MCP |
29
+ | **Cline** (VS Code extension) | `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` | Settings UI |
30
+ | **Continue** (VS Code extension) | `~/.continue/config.yaml` | `mcpServers:` section |
31
+ | **Windsurf** | `~/.codeium/windsurf/mcp_config.json` | Settings UI |
32
+ | **Zed** | `~/.config/zed/settings.json` (`context_servers`) | Native MCP |
33
+ | **JetBrains AI Assistant** (2024.3+) | Settings → Tools → AI Assistant → MCP | Built-in |
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ # No install needed — use npx
39
+ npx -y sphior-code-mcp
40
+
41
+ # Or install globally
42
+ npm install -g sphior-code-mcp
43
+ sphior-code-mcp
44
+ ```
45
+
46
+ ## Configuration
47
+
48
+ Set your API key from [sphior.com/account/code/api-keys](https://sphior.com/account/code/api-keys):
49
+
50
+ ```bash
51
+ export SPHIOR_API_KEY=sk_live_xxxxxxxxxxxx
52
+ ```
53
+
54
+ ### Environment variables
55
+
56
+ | Variable | Required | Default | Description |
57
+ |---|---|---|---|
58
+ | `SPHIOR_API_KEY` | ✅ Yes | — | Bearer token from your SPHIOR Code account |
59
+ | `SPHIOR_API_BASE` | No | `https://sphior.com/api/v1` | Override for self-hosted / regional deployments |
60
+ | `SPHIOR_TIMEOUT` | No | `30000` | Request timeout in ms (1000–300000) |
61
+ | `SPHIOR_DEBUG` | No | `false` | Enable verbose logging to stderr |
62
+
63
+ ## Example config (Cursor / Claude Code / VS Code style)
64
+
65
+ ```json
66
+ {
67
+ "mcpServers": {
68
+ "sphior-code": {
69
+ "command": "npx",
70
+ "args": ["-y", "sphior-code-mcp"],
71
+ "env": {
72
+ "SPHIOR_API_KEY": "sk_live_xxxxxxxxxxxx"
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ For **GitHub Copilot in VS Code**, use `"servers"` instead of `"mcpServers"`:
80
+
81
+ ```json
82
+ {
83
+ "servers": {
84
+ "sphior-code": {
85
+ "type": "stdio",
86
+ "command": "npx",
87
+ "args": ["-y", "sphior-code-mcp"],
88
+ "env": {
89
+ "SPHIOR_API_KEY": "sk_live_xxxxxxxxxxxx"
90
+ }
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Tools exposed
97
+
98
+ | Tool | Purpose |
99
+ |---|---|
100
+ | `list_findings` | List vulnerabilities (filter by severity / status / limit) |
101
+ | `get_finding` | Full details for one finding (CVSS, CWE, file path, fix hint) |
102
+ | `get_security_summary` | Posture overview (counts by severity, last scan, repos monitored) |
103
+ | `get_fix_proposal` | AI-generated patch (code + explanation + post-fix CVSS) |
104
+ | `resolve_finding` | Mark as fixed |
105
+ | `mark_false_positive` | Mark as not exploitable |
106
+ | `health_check` | Verify connection + auth |
107
+
108
+ ## Resources exposed
109
+
110
+ - `sphior-code://summary` — JSON snapshot of current posture
111
+ - `sphior-code://findings/{id}` — full detail per finding (auto-listed for open findings)
112
+
113
+ ## Reliability
114
+
115
+ - **Exponential backoff retry** on 5xx / network errors (3 attempts)
116
+ - **30-second request timeout** (configurable)
117
+ - **Graceful degradation** — auth errors fail fast, server errors retry
118
+ - **Structured errors** with actionable hints
119
+ - **stderr-only logging** (stdout is reserved for MCP protocol)
120
+
121
+ ## Development
122
+
123
+ ```bash
124
+ # In this directory
125
+ npm install
126
+ npm run build
127
+ SPHIOR_API_KEY=sk_test_xxx node bin/sphior-code-mcp.js
128
+ # Type a JSON-RPC request to test
129
+ ```
130
+
131
+ ## License
132
+
133
+ MIT © SPHIOR Security
134
+
135
+ ## Links
136
+
137
+ - 🌐 [SPHIOR Code](https://sphior.com/code)
138
+ - 📖 [API Reference](https://sphior.com/docs/api)
139
+ - 🐛 [Report issues](https://github.com/sphior/code-mcp/issues)
140
+ - 🔑 [Get an API key](https://sphior.com/account/code/api-keys)
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sphior-code-mcp — Stdio entrypoint for MCP clients.
4
+ *
5
+ * 起動方法:
6
+ * SPHIOR_API_KEY=sk_live_xxx npx -y @sphior/code-mcp
7
+ *
8
+ * 環境変数:
9
+ * SPHIOR_API_KEY (required) Bearer API key from sphior.com/account/code/api-keys
10
+ * SPHIOR_API_BASE (optional) Override base URL. Default: https://sphior.com/api/v1
11
+ * SPHIOR_TIMEOUT (optional) Request timeout in ms. Default: 30000
12
+ * SPHIOR_DEBUG (optional) Enable debug logging to stderr. Default: false
13
+ */
14
+
15
+ import { startServer } from "../dist/index.js";
16
+
17
+ startServer().catch((err) => {
18
+ // stderr only — stdout is reserved for the MCP protocol
19
+ process.stderr.write(`[sphior-code-mcp] Fatal: ${err?.message ?? String(err)}\n`);
20
+ process.exit(1);
21
+ });
@@ -0,0 +1,95 @@
1
+ /**
2
+ * api-client.ts — SPHIOR CODE REST API クライアント
3
+ *
4
+ * 機能:
5
+ * - Bearer 認証
6
+ * - Exponential backoff retry (5xx, network, timeout)
7
+ * - 構造化エラー (status code + hint message)
8
+ * - タイムアウト保護 (AbortSignal)
9
+ * - User-Agent でバージョン送信
10
+ */
11
+ export interface Finding {
12
+ id: string;
13
+ severity: "critical" | "high" | "medium" | "low";
14
+ rule_type: string;
15
+ title: string;
16
+ message: string;
17
+ file_path: string;
18
+ line_start: number;
19
+ language: string | null;
20
+ cwe: string | null;
21
+ cvss_base: number | null;
22
+ fix_hint: string | null;
23
+ fix_available: boolean;
24
+ resolved_at: string | null;
25
+ false_positive_marked: boolean;
26
+ risk_accepted: boolean;
27
+ repo_full_name: string | null;
28
+ created_at: string;
29
+ }
30
+ export interface FindingDetail extends Finding {
31
+ instance_key: string;
32
+ finding_key: string;
33
+ pr_number: number | null;
34
+ commit_sha: string | null;
35
+ owasp: string | null;
36
+ column_start: number | null;
37
+ last_seen: string;
38
+ }
39
+ export interface SecuritySummary {
40
+ total_open: number;
41
+ critical: number;
42
+ high: number;
43
+ medium: number;
44
+ low: number;
45
+ last_scan_at: string | null;
46
+ repos_monitored: number;
47
+ }
48
+ export interface FixProposal {
49
+ explanation: string;
50
+ patched_code: string;
51
+ test_suggestion: string | null;
52
+ cvss_after_fix: number | null;
53
+ }
54
+ export declare class SphiorApiError extends Error {
55
+ readonly status: number;
56
+ readonly endpoint: string;
57
+ readonly hint?: string | undefined;
58
+ constructor(status: number, endpoint: string, message: string, hint?: string | undefined);
59
+ /** MCP クライアント向けの人間可読フォーマット */
60
+ toUserMessage(): string;
61
+ }
62
+ export declare const api: {
63
+ listFindings(opts?: {
64
+ severity?: string;
65
+ status?: string;
66
+ limit?: number;
67
+ }): Promise<{
68
+ findings: Finding[];
69
+ }>;
70
+ getFinding(findingId: string): Promise<{
71
+ finding: FindingDetail;
72
+ }>;
73
+ getSummary(): Promise<{
74
+ summary: SecuritySummary;
75
+ }>;
76
+ getFixProposal(findingId: string): Promise<{
77
+ fix: FixProposal | null;
78
+ }>;
79
+ resolveFinding(findingId: string, reason?: string): Promise<{
80
+ message: string;
81
+ }>;
82
+ markFalsePositive(findingId: string, reason?: string): Promise<{
83
+ message: string;
84
+ }>;
85
+ verifyEvidence(opts?: {
86
+ repo?: string;
87
+ includePack?: boolean;
88
+ }): Promise<unknown>;
89
+ getFixContext(opts?: {
90
+ repo?: string;
91
+ findingId?: string;
92
+ severity?: string;
93
+ }): Promise<unknown>;
94
+ };
95
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ /**
2
+ * api-client.ts — SPHIOR CODE REST API クライアント
3
+ *
4
+ * 機能:
5
+ * - Bearer 認証
6
+ * - Exponential backoff retry (5xx, network, timeout)
7
+ * - 構造化エラー (status code + hint message)
8
+ * - タイムアウト保護 (AbortSignal)
9
+ * - User-Agent でバージョン送信
10
+ */
11
+ import { CONFIG } from "./config.js";
12
+ import { log } from "./logger.js";
13
+ // ── Error ─────────────────────────────────────────────────────────────────────
14
+ export class SphiorApiError extends Error {
15
+ status;
16
+ endpoint;
17
+ hint;
18
+ constructor(status, endpoint, message, hint) {
19
+ super(message);
20
+ this.status = status;
21
+ this.endpoint = endpoint;
22
+ this.hint = hint;
23
+ this.name = "SphiorApiError";
24
+ }
25
+ /** MCP クライアント向けの人間可読フォーマット */
26
+ toUserMessage() {
27
+ const lines = [`${this.message} (status ${this.status} on ${this.endpoint})`];
28
+ if (this.hint)
29
+ lines.push(`Hint: ${this.hint}`);
30
+ return lines.join("\n");
31
+ }
32
+ }
33
+ // ── Retry helper ──────────────────────────────────────────────────────────────
34
+ const MAX_RETRIES = 3;
35
+ const BACKOFF_BASE = 500; // ms
36
+ async function withRetry(label, fn) {
37
+ let lastErr;
38
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
39
+ try {
40
+ return await fn();
41
+ }
42
+ catch (err) {
43
+ lastErr = err;
44
+ // 4xx は retry しない
45
+ if (err instanceof SphiorApiError && err.status < 500 && err.status !== 0) {
46
+ throw err;
47
+ }
48
+ if (attempt === MAX_RETRIES - 1)
49
+ break;
50
+ const delay = BACKOFF_BASE * Math.pow(2, attempt); // 500ms → 1s → 2s
51
+ log.warn(`${label} failed (attempt ${attempt + 1}/${MAX_RETRIES}), retrying in ${delay}ms`, {
52
+ error: err instanceof Error ? err.message : String(err),
53
+ });
54
+ await new Promise((r) => setTimeout(r, delay));
55
+ }
56
+ }
57
+ throw lastErr;
58
+ }
59
+ async function request(path, opts = {}) {
60
+ const method = opts.method ?? "GET";
61
+ // query string 構築 (undefined はスキップ)
62
+ let url = `${CONFIG.baseUrl}${path}`;
63
+ if (opts.query) {
64
+ const qs = new URLSearchParams();
65
+ for (const [k, v] of Object.entries(opts.query)) {
66
+ if (v !== undefined && v !== null)
67
+ qs.set(k, String(v));
68
+ }
69
+ const q = qs.toString();
70
+ if (q)
71
+ url += `?${q}`;
72
+ }
73
+ const endpoint = `${method} ${path}`;
74
+ return withRetry(endpoint, async () => {
75
+ log.debug(`→ ${endpoint}`);
76
+ const controller = new AbortController();
77
+ const timer = setTimeout(() => controller.abort(), CONFIG.timeoutMs);
78
+ let res;
79
+ try {
80
+ res = await fetch(url, {
81
+ method,
82
+ headers: {
83
+ "Authorization": `Bearer ${CONFIG.apiKey}`,
84
+ "Content-Type": "application/json",
85
+ "User-Agent": `sphior-code-mcp/${CONFIG.version} node/${process.versions.node}`,
86
+ },
87
+ body: opts.body ? JSON.stringify(opts.body) : undefined,
88
+ signal: controller.signal,
89
+ });
90
+ }
91
+ catch (err) {
92
+ clearTimeout(timer);
93
+ // ネットワーク / abort
94
+ const msg = err instanceof Error ? err.message : String(err);
95
+ throw new SphiorApiError(0, endpoint, `Network error: ${msg}`, "Check your internet connection and SPHIOR_API_BASE setting.");
96
+ }
97
+ clearTimeout(timer);
98
+ if (!res.ok) {
99
+ let errBody = {};
100
+ try {
101
+ errBody = (await res.json());
102
+ }
103
+ catch { /* non-JSON error body */ }
104
+ const message = errBody.error ?? `HTTP ${res.status} ${res.statusText}`;
105
+ const hint = errBody.hint ?? (res.status === 401
106
+ ? "Verify SPHIOR_API_KEY is valid and not revoked."
107
+ : res.status === 429
108
+ ? "Rate limit exceeded. Retry after a few seconds."
109
+ : undefined);
110
+ throw new SphiorApiError(res.status, endpoint, message, hint);
111
+ }
112
+ log.debug(`← ${endpoint} 200`);
113
+ return (await res.json());
114
+ });
115
+ }
116
+ // ── Public API methods ────────────────────────────────────────────────────────
117
+ export const api = {
118
+ listFindings(opts = {}) {
119
+ return request("/code/findings", { query: { severity: opts.severity, status: opts.status, limit: opts.limit } });
120
+ },
121
+ getFinding(findingId) {
122
+ return request(`/code/findings/${encodeURIComponent(findingId)}`);
123
+ },
124
+ getSummary() {
125
+ return request("/code/summary");
126
+ },
127
+ getFixProposal(findingId) {
128
+ return request(`/code/findings/${encodeURIComponent(findingId)}/fix`);
129
+ },
130
+ resolveFinding(findingId, reason) {
131
+ return request(`/code/findings/${encodeURIComponent(findingId)}/resolve`, {
132
+ method: "POST",
133
+ body: { reason },
134
+ });
135
+ },
136
+ markFalsePositive(findingId, reason) {
137
+ return request(`/code/findings/${encodeURIComponent(findingId)}/false-positive`, {
138
+ method: "POST",
139
+ body: { reason },
140
+ });
141
+ },
142
+ // 改ざん不可の監査証跡(決定論エンジン)の独立検証。監査人向け。
143
+ verifyEvidence(opts = {}) {
144
+ return request("/code/evidence", { query: { repo: opts.repo, pack: opts.includePack ? "1" : undefined } });
145
+ },
146
+ // 決定論 finding の修正コンテキスト(顧客 AI が直すための payload・コード非送信)。
147
+ getFixContext(opts = {}) {
148
+ return request("/code/evidence/fix-context", {
149
+ query: { repo: opts.repo, finding_id: opts.findingId, severity: opts.severity },
150
+ });
151
+ },
152
+ };
153
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * config.ts — Environment-driven configuration with defaults.
3
+ *
4
+ * 環境変数から設定を読み、不正値・必須値欠落を起動時にチェックする。
5
+ */
6
+ export interface Config {
7
+ apiKey: string;
8
+ baseUrl: string;
9
+ timeoutMs: number;
10
+ debug: boolean;
11
+ /** Package version (populated by build) */
12
+ version: string;
13
+ }
14
+ export declare const CONFIG: Config;
15
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,MAAM;IACrB,MAAM,EAAG,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAqCD,eAAO,MAAM,MAAM,EAAE,MAAiC,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,33 @@
1
+ /**
2
+ * config.ts — Environment-driven configuration with defaults.
3
+ *
4
+ * 環境変数から設定を読み、不正値・必須値欠落を起動時にチェックする。
5
+ */
6
+ const PACKAGE_VERSION = "1.0.0";
7
+ function readEnv() {
8
+ const apiKey = process.env.SPHIOR_API_KEY?.trim();
9
+ if (!apiKey) {
10
+ throw new Error("SPHIOR_API_KEY environment variable is required.\n" +
11
+ "Get your API key at: https://sphior.com/account/code/api-keys");
12
+ }
13
+ if (!apiKey.startsWith("sk_")) {
14
+ throw new Error(`Invalid SPHIOR_API_KEY format (expected sk_live_... or sk_test_...).\n` +
15
+ `Get your API key at: https://sphior.com/account/code/api-keys`);
16
+ }
17
+ const baseUrl = (process.env.SPHIOR_API_BASE?.trim() || "https://sphior.com/api/v1").replace(/\/+$/, "");
18
+ const timeoutMs = Number(process.env.SPHIOR_TIMEOUT ?? "30000");
19
+ const debug = ["1", "true", "yes", "on"].includes((process.env.SPHIOR_DEBUG ?? "").toLowerCase());
20
+ if (!Number.isFinite(timeoutMs) || timeoutMs < 1000 || timeoutMs > 300_000) {
21
+ throw new Error(`SPHIOR_TIMEOUT must be between 1000 and 300000 ms (got: ${timeoutMs}).`);
22
+ }
23
+ return {
24
+ apiKey,
25
+ baseUrl,
26
+ timeoutMs,
27
+ debug,
28
+ version: PACKAGE_VERSION,
29
+ };
30
+ }
31
+ // 起動時に 1 度だけ読み込んで凍結
32
+ export const CONFIG = Object.freeze(readEnv());
33
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC,SAAS,OAAO;IACd,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC;IAClD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,oDAAoD;YACpD,+DAA+D,CAChE,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CACb,wEAAwE;YACxE,+DAA+D,CAChE,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,2BAA2B,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzG,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,CAAC;IAChE,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAElG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,GAAG,IAAI,IAAI,SAAS,GAAG,OAAO,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,2DAA2D,SAAS,IAAI,CAAC,CAAC;IAC5F,CAAC;IAED,OAAO;QACL,MAAM;QACN,OAAO;QACP,SAAS;QACT,KAAK;QACL,OAAO,EAAE,eAAe;KACzB,CAAC;AACJ,CAAC;AAED,oBAAoB;AACpB,MAAM,CAAC,MAAM,MAAM,GAAW,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * SPHIOR Code MCP — Public entrypoint.
3
+ *
4
+ * Exports:
5
+ * - startServer(): Promise<void> — start the stdio MCP server
6
+ * - Types from api-client for programmatic use
7
+ */
8
+ export { startServer } from "./server.js";
9
+ export type { Finding, FindingDetail, SecuritySummary, FixProposal, } from "./api-client.js";
10
+ export { SphiorApiError } from "./api-client.js";
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,YAAY,EACV,OAAO,EACP,aAAa,EACb,eAAe,EACf,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * SPHIOR Code MCP — Public entrypoint.
3
+ *
4
+ * Exports:
5
+ * - startServer(): Promise<void> — start the stdio MCP server
6
+ * - Types from api-client for programmatic use
7
+ */
8
+ export { startServer } from "./server.js";
9
+ export { SphiorApiError } from "./api-client.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * logger.ts — stderr-only logger (MCP の stdout を汚さない)
3
+ *
4
+ * MCP プロトコルは stdout 上で JSON-RPC メッセージを交換するため、
5
+ * console.log() は使用厳禁。すべてのログは stderr に出力する。
6
+ */
7
+ export declare const log: {
8
+ error: (msg: string, meta?: Record<string, unknown>) => void;
9
+ warn: (msg: string, meta?: Record<string, unknown>) => void;
10
+ info: (msg: string, meta?: Record<string, unknown>) => void;
11
+ debug: (msg: string, meta?: Record<string, unknown>) => void;
12
+ };
13
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAoBH,eAAO,MAAM,GAAG;iBACD,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;gBAC7C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;gBAC7C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;iBAC7C,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,IAAI;CAC3D,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * logger.ts — stderr-only logger (MCP の stdout を汚さない)
3
+ *
4
+ * MCP プロトコルは stdout 上で JSON-RPC メッセージを交換するため、
5
+ * console.log() は使用厳禁。すべてのログは stderr に出力する。
6
+ */
7
+ import { CONFIG } from "./config.js";
8
+ const LEVELS = { error: 0, warn: 1, info: 2, debug: 3 };
9
+ function shouldLog(level) {
10
+ const threshold = CONFIG.debug ? LEVELS.debug : LEVELS.info;
11
+ return LEVELS[level] <= threshold;
12
+ }
13
+ function write(level, message, meta) {
14
+ if (!shouldLog(level))
15
+ return;
16
+ const ts = new Date().toISOString();
17
+ const tag = `[sphior-code-mcp]`;
18
+ const extra = meta ? ` ${JSON.stringify(meta)}` : "";
19
+ process.stderr.write(`${ts} ${tag} ${level.toUpperCase()} ${message}${extra}\n`);
20
+ }
21
+ export const log = {
22
+ error: (msg, meta) => write("error", msg, meta),
23
+ warn: (msg, meta) => write("warn", msg, meta),
24
+ info: (msg, meta) => write("info", msg, meta),
25
+ debug: (msg, meta) => write("debug", msg, meta),
26
+ };
27
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAW,CAAC;AAGjE,SAAS,SAAS,CAAC,KAAY;IAC7B,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;IAC5D,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC;AACpC,CAAC;AAED,SAAS,KAAK,CAAC,KAAY,EAAE,OAAe,EAAE,IAA8B;IAC1E,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,OAAO;IAC9B,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,mBAAmB,CAAC;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,IAAI,GAAG,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,KAAK,EAAE,CAAC,GAAW,EAAE,IAA8B,EAAQ,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;IACvF,IAAI,EAAG,CAAC,GAAW,EAAE,IAA8B,EAAQ,EAAE,CAAC,KAAK,CAAC,MAAM,EAAG,GAAG,EAAE,IAAI,CAAC;IACvF,IAAI,EAAG,CAAC,GAAW,EAAE,IAA8B,EAAQ,EAAE,CAAC,KAAK,CAAC,MAAM,EAAG,GAAG,EAAE,IAAI,CAAC;IACvF,KAAK,EAAE,CAAC,GAAW,EAAE,IAA8B,EAAQ,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC;CACxF,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * server.ts — MCP Server セットアップ (stdio transport)
3
+ *
4
+ * tools/resources を登録し、JSON-RPC リクエストを処理する。
5
+ */
6
+ export declare function startServer(): Promise<void>;
7
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgBH,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoHjD"}
package/dist/server.js ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * server.ts — MCP Server セットアップ (stdio transport)
3
+ *
4
+ * tools/resources を登録し、JSON-RPC リクエストを処理する。
5
+ */
6
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
7
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
8
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
9
+ import { z } from "zod";
10
+ import { CONFIG } from "./config.js";
11
+ import { log } from "./logger.js";
12
+ import { TOOLS, HANDLERS } from "./tools/index.js";
13
+ import { api } from "./api-client.js";
14
+ export async function startServer() {
15
+ log.info(`SPHIOR Code MCP server starting`, { version: CONFIG.version, baseUrl: CONFIG.baseUrl });
16
+ const server = new Server({
17
+ name: "sphior-code",
18
+ version: CONFIG.version,
19
+ }, {
20
+ capabilities: {
21
+ tools: {},
22
+ resources: {},
23
+ },
24
+ });
25
+ // ── tools/list ──────────────────────────────────────────────────────────
26
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
27
+ tools: TOOLS,
28
+ }));
29
+ // ── tools/call ──────────────────────────────────────────────────────────
30
+ // SDK 1.29+ では handler 戻り値の型が ServerResult union に拡張されているため
31
+ // ローカル ToolResult 形式 ({content, isError}) を CallToolResult として返す。
32
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
33
+ const { name, arguments: args } = request.params;
34
+ log.debug(`tools/call ${name}`, { args });
35
+ const handler = HANDLERS[name];
36
+ if (!handler) {
37
+ return {
38
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
39
+ isError: true,
40
+ };
41
+ }
42
+ try {
43
+ const result = await handler(args);
44
+ return result;
45
+ }
46
+ catch (e) {
47
+ // Zod 検証エラーなど handler 内で投げられた未捕捉例外
48
+ if (e instanceof z.ZodError) {
49
+ const msg = `Invalid arguments for ${name}: ${e.issues.map((i) => `${i.path.join(".")} - ${i.message}`).join("; ")}`;
50
+ return { content: [{ type: "text", text: msg }], isError: true };
51
+ }
52
+ const msg = e instanceof Error ? e.message : String(e);
53
+ log.error("Unhandled tool error", { tool: name, error: msg });
54
+ return { content: [{ type: "text", text: `Internal error: ${msg}` }], isError: true };
55
+ }
56
+ });
57
+ // ── resources/list — 動的 URI で findings を露出 ─────────────────────────
58
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
59
+ try {
60
+ const { findings } = await api.listFindings({ status: "open", limit: 50 });
61
+ return {
62
+ resources: [
63
+ {
64
+ uri: "sphior-code://summary",
65
+ name: "Security Summary",
66
+ description: "Aggregate security posture (counts by severity, last scan time)",
67
+ mimeType: "application/json",
68
+ },
69
+ ...findings.map((f) => ({
70
+ uri: `sphior-code://findings/${f.id}`,
71
+ name: `${f.severity.toUpperCase()} — ${f.title}`,
72
+ description: `${f.file_path}:${f.line_start} · ${f.repo_full_name ?? "unknown repo"}`,
73
+ mimeType: "application/json",
74
+ })),
75
+ ],
76
+ };
77
+ }
78
+ catch (e) {
79
+ log.warn("resources/list failed", { error: e instanceof Error ? e.message : String(e) });
80
+ return { resources: [] };
81
+ }
82
+ });
83
+ // ── resources/read ──────────────────────────────────────────────────────
84
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
85
+ const uri = request.params.uri;
86
+ if (uri === "sphior-code://summary") {
87
+ const { summary } = await api.getSummary();
88
+ return {
89
+ contents: [
90
+ { uri, mimeType: "application/json", text: JSON.stringify(summary, null, 2) },
91
+ ],
92
+ };
93
+ }
94
+ const match = uri.match(/^sphior-code:\/\/findings\/(.+)$/);
95
+ if (match) {
96
+ const findingId = match[1];
97
+ const { finding } = await api.getFinding(findingId);
98
+ return {
99
+ contents: [
100
+ { uri, mimeType: "application/json", text: JSON.stringify(finding, null, 2) },
101
+ ],
102
+ };
103
+ }
104
+ throw new Error(`Unsupported resource URI: ${uri}`);
105
+ });
106
+ // ── Transport 接続 ──────────────────────────────────────────────────────
107
+ const transport = new StdioServerTransport();
108
+ await server.connect(transport);
109
+ log.info(`Ready to receive MCP requests on stdio`);
110
+ // SIGTERM / SIGINT で graceful shutdown
111
+ const shutdown = (signal) => {
112
+ log.info(`Shutting down on ${signal}`);
113
+ process.exit(0);
114
+ };
115
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
116
+ process.on("SIGINT", () => shutdown("SIGINT"));
117
+ }
118
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * tools/index.ts — MCP tool 定義一覧
3
+ *
4
+ * 各 tool は:
5
+ * - definition: MCP プロトコル仕様で公開するメタ情報
6
+ * - handler: 実際の処理 (api クライアントを呼び出して structured 結果を返す)
7
+ *
8
+ * Zod schema で実行時バリデーションし、不正パラメータは早期エラー化する。
9
+ */
10
+ import type { Tool } from "@modelcontextprotocol/sdk/types.js";
11
+ interface ToolResult {
12
+ content: Array<{
13
+ type: "text";
14
+ text: string;
15
+ }>;
16
+ isError?: boolean;
17
+ }
18
+ export declare const TOOLS: Tool[];
19
+ type Handler = (args: unknown) => Promise<ToolResult>;
20
+ export declare const HANDLERS: Record<string, Handler>;
21
+ export {};
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAM/D,UAAU,UAAU;IAClB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAiED,eAAO,MAAM,KAAK,EAAE,IAAI,EAwIvB,CAAC;AAIF,KAAK,OAAO,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAoD5C,CAAC"}
@@ -0,0 +1,238 @@
1
+ /**
2
+ * tools/index.ts — MCP tool 定義一覧
3
+ *
4
+ * 各 tool は:
5
+ * - definition: MCP プロトコル仕様で公開するメタ情報
6
+ * - handler: 実際の処理 (api クライアントを呼び出して structured 結果を返す)
7
+ *
8
+ * Zod schema で実行時バリデーションし、不正パラメータは早期エラー化する。
9
+ */
10
+ import { z } from "zod";
11
+ import { api, SphiorApiError } from "../api-client.js";
12
+ import { log } from "../logger.js";
13
+ function ok(payload) {
14
+ return {
15
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }],
16
+ };
17
+ }
18
+ function err(message) {
19
+ return {
20
+ content: [{ type: "text", text: message }],
21
+ isError: true,
22
+ };
23
+ }
24
+ async function safe(fn) {
25
+ try {
26
+ const result = await fn();
27
+ return ok(result);
28
+ }
29
+ catch (e) {
30
+ if (e instanceof SphiorApiError) {
31
+ return err(e.toUserMessage());
32
+ }
33
+ const msg = e instanceof Error ? e.message : String(e);
34
+ log.error("Unexpected tool error", { error: msg });
35
+ return err(`Internal error: ${msg}`);
36
+ }
37
+ }
38
+ // ── Schemas ───────────────────────────────────────────────────────────────────
39
+ const SeverityEnum = z.enum(["critical", "high", "medium", "low"]);
40
+ const StatusEnum = z.enum(["open", "resolved", "all"]);
41
+ const ListFindingsArgs = z.object({
42
+ severity: SeverityEnum.optional().describe("Filter by severity"),
43
+ status: StatusEnum.optional().describe("Filter by triage status. Default: open"),
44
+ limit: z.number().int().min(1).max(100).optional().describe("Max number of results (1-100). Default: 20"),
45
+ });
46
+ const FindingIdArgs = z.object({
47
+ findingId: z.string().min(1).describe("Finding UUID — obtain via list_findings"),
48
+ });
49
+ const ResolveArgs = FindingIdArgs.extend({
50
+ reason: z.string().max(500).optional().describe("Optional human-readable reason for closing"),
51
+ });
52
+ const FpArgs = FindingIdArgs.extend({
53
+ reason: z.string().max(500).optional().describe("Optional reason why this is a false positive"),
54
+ });
55
+ const VerifyEvidenceArgs = z.object({
56
+ repo: z.string().optional().describe("Repository full_name (owner/repo). Omit for all."),
57
+ includePack: z.boolean().optional().describe("Include the independently-verifiable evidence pack (records + SHA-256 manifest)."),
58
+ });
59
+ const FixContextArgs = z.object({
60
+ repo: z.string().optional().describe("Repository full_name (owner/repo). Omit for the latest scanned repo."),
61
+ findingId: z.string().optional().describe("A specific finding fingerprint to fix. Omit for all findings."),
62
+ severity: SeverityEnum.optional().describe("Filter to one severity."),
63
+ });
64
+ // ── Tool definitions (MCP 仕様) ───────────────────────────────────────────────
65
+ export const TOOLS = [
66
+ {
67
+ name: "list_findings",
68
+ description: "List security vulnerabilities (SAST + SCA) detected by SPHIOR CODE across the user's GitHub repositories. " +
69
+ "Use this when the user asks about security issues, vulnerabilities, or CVEs in their code. " +
70
+ "Returns up to 100 findings ordered by detection date (newest first).",
71
+ inputSchema: {
72
+ type: "object",
73
+ properties: {
74
+ severity: {
75
+ type: "string",
76
+ enum: ["critical", "high", "medium", "low"],
77
+ description: "Filter by severity level",
78
+ },
79
+ status: {
80
+ type: "string",
81
+ enum: ["open", "resolved", "all"],
82
+ description: "Filter by triage status. Default: open",
83
+ },
84
+ limit: {
85
+ type: "number",
86
+ minimum: 1,
87
+ maximum: 100,
88
+ description: "Max number of results (1-100). Default: 20",
89
+ },
90
+ },
91
+ },
92
+ },
93
+ {
94
+ name: "get_finding",
95
+ description: "Fetch full details of a single security finding by ID — includes CVSS score, CWE classification, " +
96
+ "exact file path and line number, vulnerability message, and fix hint. " +
97
+ "Use when the user wants to investigate a specific issue from list_findings.",
98
+ inputSchema: {
99
+ type: "object",
100
+ properties: {
101
+ findingId: { type: "string", description: "Finding UUID — obtain via list_findings" },
102
+ },
103
+ required: ["findingId"],
104
+ },
105
+ },
106
+ {
107
+ name: "get_security_summary",
108
+ description: "Get the user's overall security posture: counts by severity, last scan time, and number of monitored repos. " +
109
+ "Use this when the user wants a high-level overview of their security health.",
110
+ inputSchema: {
111
+ type: "object",
112
+ properties: {},
113
+ },
114
+ },
115
+ {
116
+ name: "get_fix_proposal",
117
+ description: "Fetch the AI-generated fix proposal for a specific finding — includes patched code, " +
118
+ "explanation of the change, and CVSS score after applying the fix. " +
119
+ "Use when the user wants to see how to fix a vulnerability.",
120
+ inputSchema: {
121
+ type: "object",
122
+ properties: {
123
+ findingId: { type: "string", description: "Finding UUID — obtain via list_findings" },
124
+ },
125
+ required: ["findingId"],
126
+ },
127
+ },
128
+ {
129
+ name: "resolve_finding",
130
+ description: "Mark a finding as resolved (e.g., after applying a fix). " +
131
+ "Use only when the vulnerability has actually been remediated. " +
132
+ "For false positives, use mark_false_positive instead.",
133
+ inputSchema: {
134
+ type: "object",
135
+ properties: {
136
+ findingId: { type: "string", description: "Finding UUID" },
137
+ reason: { type: "string", maxLength: 500, description: "Optional reason for closing" },
138
+ },
139
+ required: ["findingId"],
140
+ },
141
+ },
142
+ {
143
+ name: "mark_false_positive",
144
+ description: "Mark a finding as a false positive (the reported vulnerability is not actually exploitable). " +
145
+ "Use this when the AI's detection is incorrect for a specific code context.",
146
+ inputSchema: {
147
+ type: "object",
148
+ properties: {
149
+ findingId: { type: "string", description: "Finding UUID" },
150
+ reason: { type: "string", maxLength: 500, description: "Optional reason why this is a false positive" },
151
+ },
152
+ required: ["findingId"],
153
+ },
154
+ },
155
+ {
156
+ name: "health_check",
157
+ description: "Verify connectivity and authentication with the SPHIOR CODE API. " +
158
+ "Returns service version and current security summary. " +
159
+ "Use this to debug connection issues.",
160
+ inputSchema: {
161
+ type: "object",
162
+ properties: {},
163
+ },
164
+ },
165
+ {
166
+ name: "get_fix_context",
167
+ description: "Get deterministic remediation guidance for SPHIOR's code findings so YOU (the AI agent) can fix them. " +
168
+ "SPHIOR does not generate code or transmit source — open the referenced file in your workspace, read the " +
169
+ "code yourself, and apply the fix. Returns why-it-matters, remediation steps, exact location, and references. " +
170
+ "A human must review before merge.",
171
+ inputSchema: {
172
+ type: "object",
173
+ properties: {
174
+ repo: { type: "string", description: "Repository full_name (owner/repo). Omit for the latest scanned repo." },
175
+ findingId: { type: "string", description: "A specific finding fingerprint to fix. Omit for all findings." },
176
+ severity: { type: "string", enum: ["critical", "high", "medium", "low"], description: "Filter to one severity." },
177
+ },
178
+ },
179
+ },
180
+ {
181
+ name: "verify_evidence",
182
+ description: "Independently verify SPHIOR's tamper-evident code evidence chain (Merkle root + hash-chain + commit anchor). " +
183
+ "Confirms the deterministic scan records were not altered — for auditors. No source code is returned.",
184
+ inputSchema: {
185
+ type: "object",
186
+ properties: {
187
+ repo: { type: "string", description: "Filter to one repository (full_name). Omit for all." },
188
+ includePack: { type: "boolean", description: "Include the independently-verifiable evidence pack (records + SHA-256 manifest)." },
189
+ },
190
+ },
191
+ },
192
+ ];
193
+ export const HANDLERS = {
194
+ list_findings: async (args) => {
195
+ const a = ListFindingsArgs.parse(args ?? {});
196
+ return safe(() => api.listFindings(a));
197
+ },
198
+ get_finding: async (args) => {
199
+ const a = FindingIdArgs.parse(args);
200
+ return safe(() => api.getFinding(a.findingId));
201
+ },
202
+ get_security_summary: async () => {
203
+ return safe(() => api.getSummary());
204
+ },
205
+ get_fix_proposal: async (args) => {
206
+ const a = FindingIdArgs.parse(args);
207
+ return safe(() => api.getFixProposal(a.findingId));
208
+ },
209
+ resolve_finding: async (args) => {
210
+ const a = ResolveArgs.parse(args);
211
+ return safe(() => api.resolveFinding(a.findingId, a.reason));
212
+ },
213
+ mark_false_positive: async (args) => {
214
+ const a = FpArgs.parse(args);
215
+ return safe(() => api.markFalsePositive(a.findingId, a.reason));
216
+ },
217
+ health_check: async () => {
218
+ return safe(async () => {
219
+ const { summary } = await api.getSummary();
220
+ return {
221
+ status: "ok",
222
+ api_reachable: true,
223
+ repos_monitored: summary.repos_monitored,
224
+ open_findings: summary.total_open,
225
+ version: "1.0.0",
226
+ };
227
+ });
228
+ },
229
+ get_fix_context: async (args) => {
230
+ const a = FixContextArgs.parse(args ?? {});
231
+ return safe(() => api.getFixContext({ repo: a.repo, findingId: a.findingId, severity: a.severity }));
232
+ },
233
+ verify_evidence: async (args) => {
234
+ const a = VerifyEvidenceArgs.parse(args ?? {});
235
+ return safe(() => api.verifyEvidence({ repo: a.repo, includePack: a.includePack }));
236
+ },
237
+ };
238
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "sphior-code-mcp",
3
+ "version": "1.0.0",
4
+ "description": "Official Model Context Protocol (MCP) server for SPHIOR CODE — surface security findings from your GitHub repos directly into Cursor, Claude Code, VS Code, Cline, Continue, Windsurf, Zed and any MCP-compatible AI coding assistant.",
5
+ "keywords": [
6
+ "mcp",
7
+ "model-context-protocol",
8
+ "sphior",
9
+ "sphior-code",
10
+ "security",
11
+ "sast",
12
+ "sca",
13
+ "vulnerability",
14
+ "cursor",
15
+ "claude-code",
16
+ "vscode",
17
+ "cline",
18
+ "continue",
19
+ "windsurf",
20
+ "zed",
21
+ "github"
22
+ ],
23
+ "homepage": "https://sphior.com/code",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/sphior/code-mcp.git"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/sphior/code-mcp/issues"
30
+ },
31
+ "license": "MIT",
32
+ "author": "SPHIOR Security",
33
+ "type": "module",
34
+ "main": "dist/index.js",
35
+ "types": "dist/index.d.ts",
36
+ "bin": {
37
+ "sphior-code-mcp": "bin/sphior-code-mcp.js"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "bin",
42
+ "README.md",
43
+ "LICENSE"
44
+ ],
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ },
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.json",
50
+ "dev": "tsc -p tsconfig.json --watch",
51
+ "start": "node bin/sphior-code-mcp.js",
52
+ "clean": "rm -rf dist",
53
+ "prepublishOnly": "npm run clean && npm run build"
54
+ },
55
+ "dependencies": {
56
+ "@modelcontextprotocol/sdk": "^1.0.4",
57
+ "zod": "^3.23.8"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^22.10.1",
61
+ "typescript": "^5.7.2"
62
+ }
63
+ }