@systemdox/mcp-server 0.1.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/README.md +138 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +1891 -0
- package/dist/http.d.ts +30 -0
- package/dist/http.js +1623 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1561 -0
- package/dist/lib/api-client.d.ts +14 -0
- package/dist/lib/api-client.js +118 -0
- package/dist/lib/cache.d.ts +9 -0
- package/dist/lib/config.d.ts +7 -0
- package/dist/lib/context-builder.d.ts +78 -0
- package/dist/lib/context-builder.js +575 -0
- package/dist/lib/deprecation.d.ts +11 -0
- package/dist/lib/language.d.ts +7 -0
- package/dist/lib/scoring.d.ts +35 -0
- package/dist/server.d.ts +8 -0
- package/dist/tools/create-guardrail.d.ts +3 -0
- package/dist/tools/create-project-rule.d.ts +3 -0
- package/dist/tools/create-prompt-template.d.ts +3 -0
- package/dist/tools/get-context.d.ts +3 -0
- package/dist/tools/get-docs.d.ts +3 -0
- package/dist/tools/get-guardrails.d.ts +15 -0
- package/dist/tools/get-planning-context.d.ts +3 -0
- package/dist/tools/get-project-rules.d.ts +9 -0
- package/dist/tools/get-prompt-templates.d.ts +10 -0
- package/dist/tools/get-specs.d.ts +3 -0
- package/dist/tools/get-tech-stack.d.ts +3 -0
- package/dist/tools/report-decision.d.ts +3 -0
- package/dist/tools/update-spec.d.ts +3 -0
- package/package.json +65 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ServerConfig } from "./config.js";
|
|
2
|
+
export declare class SystemDoxApiClient {
|
|
3
|
+
private config;
|
|
4
|
+
private cache;
|
|
5
|
+
constructor(config: ServerConfig);
|
|
6
|
+
validate(): Promise<void>;
|
|
7
|
+
get<T>(path: string, params?: Record<string, string>): Promise<T>;
|
|
8
|
+
post<T>(path: string, body: unknown): Promise<T>;
|
|
9
|
+
put<T>(path: string, body: unknown): Promise<T>;
|
|
10
|
+
private mutate;
|
|
11
|
+
invalidateCache(path?: string): void;
|
|
12
|
+
private buildUrl;
|
|
13
|
+
private fetchRaw;
|
|
14
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/cache.ts
|
|
4
|
+
var ResponseCache = class {
|
|
5
|
+
store = /* @__PURE__ */ new Map();
|
|
6
|
+
ttlMs;
|
|
7
|
+
constructor(ttlMs) {
|
|
8
|
+
this.ttlMs = ttlMs;
|
|
9
|
+
}
|
|
10
|
+
get(key) {
|
|
11
|
+
const entry = this.store.get(key);
|
|
12
|
+
if (!entry) return void 0;
|
|
13
|
+
if (Date.now() > entry.expiresAt) {
|
|
14
|
+
this.store.delete(key);
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
return entry.data;
|
|
18
|
+
}
|
|
19
|
+
set(key, data) {
|
|
20
|
+
this.store.set(key, {
|
|
21
|
+
data,
|
|
22
|
+
expiresAt: Date.now() + this.ttlMs
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
invalidate(key) {
|
|
26
|
+
this.store.delete(key);
|
|
27
|
+
}
|
|
28
|
+
clear() {
|
|
29
|
+
this.store.clear();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// src/lib/api-client.ts
|
|
34
|
+
var SystemDoxApiClient = class {
|
|
35
|
+
config;
|
|
36
|
+
cache;
|
|
37
|
+
constructor(config) {
|
|
38
|
+
this.config = config;
|
|
39
|
+
this.cache = new ResponseCache(config.cacheTtlMs);
|
|
40
|
+
}
|
|
41
|
+
async validate() {
|
|
42
|
+
const res = await this.fetchRaw("/v1/health");
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`SystemDox API authentication failed (${res.status}). Check your SYSTEMDOX_API_KEY.`
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async get(path, params) {
|
|
50
|
+
const url = this.buildUrl(path, params);
|
|
51
|
+
const cacheKey = url.toString();
|
|
52
|
+
const cached = this.cache.get(cacheKey);
|
|
53
|
+
if (cached !== void 0) return cached;
|
|
54
|
+
const res = await this.fetchRaw(path, params);
|
|
55
|
+
if (!res.ok) {
|
|
56
|
+
const body = await res.text();
|
|
57
|
+
throw new Error(`SystemDox API error ${res.status}: ${body}`);
|
|
58
|
+
}
|
|
59
|
+
const data = await res.json();
|
|
60
|
+
this.cache.set(cacheKey, data);
|
|
61
|
+
return data;
|
|
62
|
+
}
|
|
63
|
+
async post(path, body) {
|
|
64
|
+
return this.mutate("POST", path, body);
|
|
65
|
+
}
|
|
66
|
+
async put(path, body) {
|
|
67
|
+
return this.mutate("PUT", path, body);
|
|
68
|
+
}
|
|
69
|
+
async mutate(method, path, body) {
|
|
70
|
+
const url = this.buildUrl(path);
|
|
71
|
+
const res = await fetch(url, {
|
|
72
|
+
method,
|
|
73
|
+
headers: {
|
|
74
|
+
// The API Gateway authorizer only reads the Authorization header;
|
|
75
|
+
// X-API-Key is kept for backwards compatibility.
|
|
76
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
77
|
+
"X-API-Key": this.config.apiKey,
|
|
78
|
+
"Content-Type": "application/json"
|
|
79
|
+
},
|
|
80
|
+
body: JSON.stringify(body)
|
|
81
|
+
});
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
const text = await res.text();
|
|
84
|
+
throw new Error(`SystemDox API error ${res.status}: ${text}`);
|
|
85
|
+
}
|
|
86
|
+
return await res.json();
|
|
87
|
+
}
|
|
88
|
+
invalidateCache(path) {
|
|
89
|
+
if (path) {
|
|
90
|
+
this.cache.invalidate(this.buildUrl(path).toString());
|
|
91
|
+
} else {
|
|
92
|
+
this.cache.clear();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
buildUrl(path, params) {
|
|
96
|
+
const base = this.config.apiUrl.replace(/\/+$/, "");
|
|
97
|
+
const url = new URL(`${base}${path.startsWith("/") ? "" : "/"}${path}`);
|
|
98
|
+
if (params) {
|
|
99
|
+
for (const [key, value] of Object.entries(params)) {
|
|
100
|
+
url.searchParams.set(key, value);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return url;
|
|
104
|
+
}
|
|
105
|
+
async fetchRaw(path, params) {
|
|
106
|
+
const url = this.buildUrl(path, params);
|
|
107
|
+
return fetch(url, {
|
|
108
|
+
headers: {
|
|
109
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
110
|
+
"X-API-Key": this.config.apiKey,
|
|
111
|
+
Accept: "application/json"
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
export {
|
|
117
|
+
SystemDoxApiClient
|
|
118
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export { estimateTokens } from "./scoring.js";
|
|
2
|
+
/**
|
|
3
|
+
* Structural subset of SystemDoxApiClient. Keeps the builder testable with a
|
|
4
|
+
* fake client and free of transport/auth concerns.
|
|
5
|
+
*/
|
|
6
|
+
export interface ContextApiClient {
|
|
7
|
+
get<T>(path: string, params?: Record<string, string>): Promise<T>;
|
|
8
|
+
}
|
|
9
|
+
export interface Guardrail {
|
|
10
|
+
id: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
category: string;
|
|
14
|
+
severity: string;
|
|
15
|
+
pattern: string;
|
|
16
|
+
fix: string;
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface SpecSummary {
|
|
20
|
+
specId: string;
|
|
21
|
+
name: string;
|
|
22
|
+
status: string;
|
|
23
|
+
requirementCount: number;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
}
|
|
26
|
+
export interface DocListResponse {
|
|
27
|
+
items: Array<{
|
|
28
|
+
id: string;
|
|
29
|
+
repo_full_name: string;
|
|
30
|
+
path: string;
|
|
31
|
+
title: string;
|
|
32
|
+
doc_type: string;
|
|
33
|
+
size: number;
|
|
34
|
+
synced_at: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export interface TechStackEntry {
|
|
38
|
+
id: string;
|
|
39
|
+
name: string;
|
|
40
|
+
category: string;
|
|
41
|
+
version?: string;
|
|
42
|
+
notes?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface ProjectRule {
|
|
45
|
+
id: string;
|
|
46
|
+
text: string;
|
|
47
|
+
category: string;
|
|
48
|
+
createdAt: string;
|
|
49
|
+
}
|
|
50
|
+
export interface BuildContextOptions {
|
|
51
|
+
taskDescription: string;
|
|
52
|
+
filePaths?: string[];
|
|
53
|
+
maxTokens?: number;
|
|
54
|
+
}
|
|
55
|
+
export interface ContextStats {
|
|
56
|
+
budget: number;
|
|
57
|
+
tokensUsed: number;
|
|
58
|
+
/** Ranked spec/doc items whose full text was fetched and included. */
|
|
59
|
+
itemsWithBody: number;
|
|
60
|
+
/** Items whose body fetch failed — listed by title + ID instead. */
|
|
61
|
+
bodyFailures: number;
|
|
62
|
+
/** Ranked items that appear only as a title + ID (no body fetched). */
|
|
63
|
+
itemsListed: number;
|
|
64
|
+
/** Ranked items that did not fit at all. */
|
|
65
|
+
itemsOmitted: number;
|
|
66
|
+
guardrails: number;
|
|
67
|
+
}
|
|
68
|
+
export interface ContextResult {
|
|
69
|
+
text: string;
|
|
70
|
+
stats: ContextStats;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Rank every context item against the task, then spend the token budget on the
|
|
74
|
+
* *bodies* of the highest-ranked specs and docs — fetched concurrently, clipped
|
|
75
|
+
* to a fair share of what's left, and always accompanied by the ID the agent
|
|
76
|
+
* needs to fetch the rest itself.
|
|
77
|
+
*/
|
|
78
|
+
export declare function buildContext(api: ContextApiClient, { taskDescription, filePaths, maxTokens }: BuildContextOptions): Promise<ContextResult>;
|