@ratio-mcp-qa/docs-server 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/oauth.json +71 -0
- package/dist/schemas/orders.json +167 -0
- package/dist/schemas/products.json +167 -0
- package/dist/schemas/schemas/oauth.json +71 -0
- package/dist/schemas/schemas/orders.json +167 -0
- package/dist/schemas/schemas/products.json +167 -0
- package/dist/schemas/schemas/scopes.json +52 -0
- package/dist/schemas/schemas/webhooks.json +69 -0
- package/dist/schemas/scopes.json +52 -0
- package/dist/schemas/webhooks.json +69 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +53 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/get-api-reference.d.ts +60 -0
- package/dist/tools/get-api-reference.d.ts.map +1 -0
- package/dist/tools/get-api-reference.js +53 -0
- package/dist/tools/get-api-reference.js.map +1 -0
- package/dist/tools/get-scope-map.d.ts +17 -0
- package/dist/tools/get-scope-map.d.ts.map +1 -0
- package/dist/tools/get-scope-map.js +102 -0
- package/dist/tools/get-scope-map.js.map +1 -0
- package/dist/tools/get-scopes.d.ts +63 -0
- package/dist/tools/get-scopes.d.ts.map +1 -0
- package/dist/tools/get-scopes.js +72 -0
- package/dist/tools/get-scopes.js.map +1 -0
- package/dist/tools/get-webhooks.d.ts +30 -0
- package/dist/tools/get-webhooks.d.ts.map +1 -0
- package/dist/tools/get-webhooks.js +32 -0
- package/dist/tools/get-webhooks.js.map +1 -0
- package/dist/tools/index.d.ts +15 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +110 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lookup-docs.d.ts +58 -0
- package/dist/tools/lookup-docs.d.ts.map +1 -0
- package/dist/tools/lookup-docs.js +181 -0
- package/dist/tools/lookup-docs.js.map +1 -0
- package/dist/tools/validate-code.d.ts +12 -0
- package/dist/tools/validate-code.d.ts.map +1 -0
- package/dist/tools/validate-code.js +185 -0
- package/dist/tools/validate-code.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +85 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/schema-loader.d.ts +13 -0
- package/dist/utils/schema-loader.d.ts.map +1 -0
- package/dist/utils/schema-loader.js +61 -0
- package/dist/utils/schema-loader.js.map +1 -0
- package/dist/utils/zod-to-json.d.ts +7 -0
- package/dist/utils/zod-to-json.d.ts.map +1 -0
- package/dist/utils/zod-to-json.js +63 -0
- package/dist/utils/zod-to-json.js.map +1 -0
- package/package.json +26 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* lookup_docs — Unified documentation search tool.
|
|
3
|
+
*
|
|
4
|
+
* When the LLM is unsure about any API detail, scope, webhook event, or OAuth flow,
|
|
5
|
+
* it should call this tool to get grounded, verified information from the actual
|
|
6
|
+
* documentation schemas. If the information is not found here, the LLM should tell
|
|
7
|
+
* the user it doesn't have that information rather than guessing.
|
|
8
|
+
*
|
|
9
|
+
* Searches across: API references, scopes, webhook events, and OAuth docs.
|
|
10
|
+
*/
|
|
11
|
+
interface SearchResult {
|
|
12
|
+
source: string;
|
|
13
|
+
type: 'api_endpoint' | 'scope' | 'webhook_event' | 'oauth' | 'resource';
|
|
14
|
+
relevance: 'high' | 'medium' | 'low';
|
|
15
|
+
data: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export declare function lookupDocs(input: {
|
|
18
|
+
query: string;
|
|
19
|
+
category?: string;
|
|
20
|
+
}): {
|
|
21
|
+
found: boolean;
|
|
22
|
+
message: string;
|
|
23
|
+
suggestion: string;
|
|
24
|
+
query?: undefined;
|
|
25
|
+
tokens?: undefined;
|
|
26
|
+
available_categories?: undefined;
|
|
27
|
+
available_resources?: undefined;
|
|
28
|
+
available_scope_resources?: undefined;
|
|
29
|
+
result_count?: undefined;
|
|
30
|
+
results?: undefined;
|
|
31
|
+
_instruction?: undefined;
|
|
32
|
+
} | {
|
|
33
|
+
found: boolean;
|
|
34
|
+
query: string;
|
|
35
|
+
tokens: string[];
|
|
36
|
+
message: string;
|
|
37
|
+
suggestion: string;
|
|
38
|
+
available_categories: string[];
|
|
39
|
+
available_resources: string[];
|
|
40
|
+
available_scope_resources: ("orders" | "products" | "customers" | "inventory" | "discounts" | "fulfillments" | "draft_orders" | "returns" | "shipping" | "gift_cards" | "analytics" | "channels" | "content" | "files" | "locations" | "themes" | "markets" | "reports" | "locales" | "publications" | "apps")[];
|
|
41
|
+
result_count?: undefined;
|
|
42
|
+
results?: undefined;
|
|
43
|
+
_instruction?: undefined;
|
|
44
|
+
} | {
|
|
45
|
+
found: boolean;
|
|
46
|
+
query: string;
|
|
47
|
+
result_count: number;
|
|
48
|
+
results: SearchResult[];
|
|
49
|
+
_instruction: string;
|
|
50
|
+
message?: undefined;
|
|
51
|
+
suggestion?: undefined;
|
|
52
|
+
tokens?: undefined;
|
|
53
|
+
available_categories?: undefined;
|
|
54
|
+
available_resources?: undefined;
|
|
55
|
+
available_scope_resources?: undefined;
|
|
56
|
+
};
|
|
57
|
+
export {};
|
|
58
|
+
//# sourceMappingURL=lookup-docs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookup-docs.d.ts","sourceRoot":"","sources":["../../src/tools/lookup-docs.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,UAAU,YAAY;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,cAAc,GAAG,OAAO,GAAG,eAAe,GAAG,OAAO,GAAG,UAAU,CAAC;IACxE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AA0ID,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2DrE"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { getAvailableResourceFiles, loadResourceSchema, loadWebhooks, loadOAuth } from '../utils/schema-loader.js';
|
|
2
|
+
import { SCOPES_BY_RESOURCE, PRIMARY_RESOURCES, RESOURCE_METADATA } from '@ratio-mcp-qa/shared';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
function tokenize(query) {
|
|
5
|
+
return query
|
|
6
|
+
.toLowerCase()
|
|
7
|
+
.replace(/[^a-z0-9_/\s]/g, '')
|
|
8
|
+
.split(/\s+/)
|
|
9
|
+
.filter((t) => t.length > 1);
|
|
10
|
+
}
|
|
11
|
+
function matchScore(tokens, text) {
|
|
12
|
+
const lower = text.toLowerCase();
|
|
13
|
+
let score = 0;
|
|
14
|
+
for (const token of tokens) {
|
|
15
|
+
if (lower.includes(token))
|
|
16
|
+
score++;
|
|
17
|
+
}
|
|
18
|
+
return score;
|
|
19
|
+
}
|
|
20
|
+
function searchApiEndpoints(tokens) {
|
|
21
|
+
const results = [];
|
|
22
|
+
const resources = getAvailableResourceFiles();
|
|
23
|
+
for (const resource of resources) {
|
|
24
|
+
try {
|
|
25
|
+
const schema = loadResourceSchema(resource);
|
|
26
|
+
for (const ep of schema.endpoints) {
|
|
27
|
+
const searchText = `${ep.method} ${ep.path} ${ep.summary || ''} ${ep.description || ''} ${ep.handler_name || ''} ${ep.required_scope || ''}`;
|
|
28
|
+
const score = matchScore(tokens, searchText);
|
|
29
|
+
if (score > 0) {
|
|
30
|
+
results.push({
|
|
31
|
+
source: `api/${resource}`,
|
|
32
|
+
type: 'api_endpoint',
|
|
33
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
34
|
+
data: {
|
|
35
|
+
method: ep.method,
|
|
36
|
+
path: ep.path,
|
|
37
|
+
summary: ep.summary,
|
|
38
|
+
description: ep.description,
|
|
39
|
+
required_scope: ep.required_scope,
|
|
40
|
+
handler_name: ep.handler_name,
|
|
41
|
+
resource,
|
|
42
|
+
query_params: ep.query_params || [],
|
|
43
|
+
request_body: ep.request_body || null,
|
|
44
|
+
response_schema: ep.response_schema || null,
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// Skip resources that fail to load
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return results;
|
|
55
|
+
}
|
|
56
|
+
function searchScopes(tokens) {
|
|
57
|
+
const results = [];
|
|
58
|
+
for (const [resource, scopes] of Object.entries(SCOPES_BY_RESOURCE)) {
|
|
59
|
+
const meta = RESOURCE_METADATA[resource];
|
|
60
|
+
for (const scope of scopes) {
|
|
61
|
+
const searchText = `${scope.code} ${scope.label} ${resource}`;
|
|
62
|
+
const score = matchScore(tokens, searchText);
|
|
63
|
+
if (score > 0) {
|
|
64
|
+
results.push({
|
|
65
|
+
source: `scopes/${resource}`,
|
|
66
|
+
type: 'scope',
|
|
67
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
68
|
+
data: {
|
|
69
|
+
code: scope.code,
|
|
70
|
+
label: scope.label,
|
|
71
|
+
resource,
|
|
72
|
+
codegen_ready: meta?.codegen_ready || false,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return results;
|
|
79
|
+
}
|
|
80
|
+
function searchWebhooks(tokens) {
|
|
81
|
+
const results = [];
|
|
82
|
+
try {
|
|
83
|
+
const webhooks = loadWebhooks();
|
|
84
|
+
for (const event of webhooks.events) {
|
|
85
|
+
const searchText = `${event.topic} ${event.description} ${event.resource} webhook`;
|
|
86
|
+
const score = matchScore(tokens, searchText);
|
|
87
|
+
if (score > 0) {
|
|
88
|
+
results.push({
|
|
89
|
+
source: 'webhooks',
|
|
90
|
+
type: 'webhook_event',
|
|
91
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
92
|
+
data: {
|
|
93
|
+
topic: event.topic,
|
|
94
|
+
description: event.description,
|
|
95
|
+
resource: event.resource,
|
|
96
|
+
required_scope: event.required_scope,
|
|
97
|
+
verification: webhooks.verification,
|
|
98
|
+
retry_policy: webhooks.retry_policy,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
// Skip if webhooks schema fails
|
|
106
|
+
}
|
|
107
|
+
return results;
|
|
108
|
+
}
|
|
109
|
+
function searchOAuth(tokens) {
|
|
110
|
+
const results = [];
|
|
111
|
+
try {
|
|
112
|
+
const oauth = loadOAuth();
|
|
113
|
+
const oauthText = JSON.stringify(oauth).toLowerCase();
|
|
114
|
+
const score = matchScore(tokens, oauthText);
|
|
115
|
+
if (score > 0) {
|
|
116
|
+
results.push({
|
|
117
|
+
source: 'oauth',
|
|
118
|
+
type: 'oauth',
|
|
119
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
120
|
+
data: oauth,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Skip if oauth schema fails
|
|
126
|
+
}
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
129
|
+
export function lookupDocs(input) {
|
|
130
|
+
const { query, category } = input;
|
|
131
|
+
logger.info(`[lookup_docs] query="${query}", category="${category || 'all'}"`);
|
|
132
|
+
const tokens = tokenize(query);
|
|
133
|
+
if (tokens.length === 0) {
|
|
134
|
+
return {
|
|
135
|
+
found: false,
|
|
136
|
+
message: 'Query is too short or contains no searchable terms.',
|
|
137
|
+
suggestion: 'Try searching for specific terms like "orders", "OAuth", "webhook", "scope", etc.',
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
let results = [];
|
|
141
|
+
// Search specific category or all
|
|
142
|
+
if (!category || category === 'api') {
|
|
143
|
+
results.push(...searchApiEndpoints(tokens));
|
|
144
|
+
}
|
|
145
|
+
if (!category || category === 'scopes') {
|
|
146
|
+
results.push(...searchScopes(tokens));
|
|
147
|
+
}
|
|
148
|
+
if (!category || category === 'webhooks') {
|
|
149
|
+
results.push(...searchWebhooks(tokens));
|
|
150
|
+
}
|
|
151
|
+
if (!category || category === 'oauth') {
|
|
152
|
+
results.push(...searchOAuth(tokens));
|
|
153
|
+
}
|
|
154
|
+
// Sort by relevance (high first) then deduplicate
|
|
155
|
+
results.sort((a, b) => {
|
|
156
|
+
const order = { high: 0, medium: 1, low: 2 };
|
|
157
|
+
return order[a.relevance] - order[b.relevance];
|
|
158
|
+
});
|
|
159
|
+
// Limit to top 15 results
|
|
160
|
+
results = results.slice(0, 15);
|
|
161
|
+
if (results.length === 0) {
|
|
162
|
+
return {
|
|
163
|
+
found: false,
|
|
164
|
+
query,
|
|
165
|
+
tokens,
|
|
166
|
+
message: `No documentation found matching "${query}". This information is not available in the platform documentation.`,
|
|
167
|
+
suggestion: 'Tell the user that this information is not covered in the documentation. Do NOT guess or make up an answer.',
|
|
168
|
+
available_categories: ['api', 'scopes', 'webhooks', 'oauth'],
|
|
169
|
+
available_resources: getAvailableResourceFiles(),
|
|
170
|
+
available_scope_resources: [...PRIMARY_RESOURCES],
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
found: true,
|
|
175
|
+
query,
|
|
176
|
+
result_count: results.length,
|
|
177
|
+
results,
|
|
178
|
+
_instruction: 'Use ONLY the data from these results to answer the user. Do NOT add information that is not present here.',
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=lookup-docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookup-docs.js","sourceRoot":"","sources":["../../src/tools/lookup-docs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ValidationResult } from '@ratio-mcp-qa/shared';
|
|
2
|
+
/**
|
|
3
|
+
* validate_api_code — Anti-hallucination layer.
|
|
4
|
+
* Takes generated NestJS controller/service code as string input, validates against the schema.
|
|
5
|
+
* Checks: correct endpoints, correct HTTP methods, correct scope annotations, correct handler order.
|
|
6
|
+
*/
|
|
7
|
+
export declare function validateApiCode(input: {
|
|
8
|
+
code: string;
|
|
9
|
+
resource: string;
|
|
10
|
+
scopes: string[];
|
|
11
|
+
}): ValidationResult;
|
|
12
|
+
//# sourceMappingURL=validate-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-code.d.ts","sourceRoot":"","sources":["../../src/tools/validate-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAmB,MAAM,sBAAsB,CAAC;AAwB9E;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,GAAG,gBAAgB,CAgLnB"}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { loadResourceSchema } from '../utils/schema-loader.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve scope inheritance:
|
|
4
|
+
* - write_X includes read_X
|
|
5
|
+
* - delete_X includes write_X and read_X
|
|
6
|
+
* - order-create / order-update / order-cancel include read_orders
|
|
7
|
+
*/
|
|
8
|
+
function resolveInheritedScopes(scopes) {
|
|
9
|
+
const resolved = new Set(scopes);
|
|
10
|
+
for (const scope of scopes) {
|
|
11
|
+
if (scope.startsWith('write_')) {
|
|
12
|
+
resolved.add(`read_${scope.replace('write_', '')}`);
|
|
13
|
+
}
|
|
14
|
+
else if (scope.startsWith('delete_')) {
|
|
15
|
+
const resource = scope.replace('delete_', '');
|
|
16
|
+
resolved.add(`write_${resource}`);
|
|
17
|
+
resolved.add(`read_${resource}`);
|
|
18
|
+
}
|
|
19
|
+
else if (['order-create', 'order-update', 'order-cancel'].includes(scope)) {
|
|
20
|
+
resolved.add('read_orders');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return resolved;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* validate_api_code — Anti-hallucination layer.
|
|
27
|
+
* Takes generated NestJS controller/service code as string input, validates against the schema.
|
|
28
|
+
* Checks: correct endpoints, correct HTTP methods, correct scope annotations, correct handler order.
|
|
29
|
+
*/
|
|
30
|
+
export function validateApiCode(input) {
|
|
31
|
+
const errors = [];
|
|
32
|
+
// Load the schema for the resource
|
|
33
|
+
let schema;
|
|
34
|
+
try {
|
|
35
|
+
schema = loadResourceSchema(input.resource);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return {
|
|
39
|
+
valid: false,
|
|
40
|
+
errors: [{
|
|
41
|
+
type: 'UNKNOWN_ENDPOINT',
|
|
42
|
+
message: `Unknown resource: "${input.resource}"`,
|
|
43
|
+
suggestion: `Check that a schema file exists for "${input.resource}"`,
|
|
44
|
+
}],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Resolve which scopes the developer has (including inherited by naming convention)
|
|
48
|
+
const resolvedScopes = resolveInheritedScopes(input.scopes);
|
|
49
|
+
// Get allowed endpoints based on scopes
|
|
50
|
+
const allowedEndpoints = schema.endpoints.filter((ep) => resolvedScopes.has(ep.required_scope));
|
|
51
|
+
const allowedEndpointKeys = new Set(allowedEndpoints.map((ep) => `${ep.method} ${ep.path}`));
|
|
52
|
+
// Parse code for endpoint patterns
|
|
53
|
+
// Look for: @Get(), @Post(), @Patch(), @Put(), @Delete() decorators
|
|
54
|
+
// and method names like getOrders(), createOrder(), etc.
|
|
55
|
+
const decoratorPattern = /@(Get|Post|Patch|Put|Delete)\s*\(\s*['"`]([^'"`]*)['"`]\s*\)/g;
|
|
56
|
+
const handlerPattern = /(?:async\s+)?(\w+)\s*\(/g;
|
|
57
|
+
// Extract decorators (HTTP method + path)
|
|
58
|
+
const foundEndpoints = [];
|
|
59
|
+
const lines = input.code.split('\n');
|
|
60
|
+
for (let i = 0; i < lines.length; i++) {
|
|
61
|
+
const line = lines[i];
|
|
62
|
+
const decoratorMatch = /@(Get|Post|Patch|Put|Delete)\s*\(\s*['"`]?([^'"`\)]*?)['"`]?\s*\)/.exec(line);
|
|
63
|
+
if (decoratorMatch) {
|
|
64
|
+
const method = decoratorMatch[1].toUpperCase();
|
|
65
|
+
let path = decoratorMatch[2] || '/';
|
|
66
|
+
// Look for the handler name on the next few lines
|
|
67
|
+
let handlerName;
|
|
68
|
+
for (let j = i + 1; j < Math.min(i + 5, lines.length); j++) {
|
|
69
|
+
const handlerMatch = /(?:async\s+)?(\w+)\s*\(/.exec(lines[j]);
|
|
70
|
+
if (handlerMatch && !['if', 'for', 'while', 'switch', 'catch'].includes(handlerMatch[1])) {
|
|
71
|
+
handlerName = handlerMatch[1];
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
foundEndpoints.push({ method, path, line: i + 1, handlerName });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Check for @Controller decorator to get base path
|
|
79
|
+
const controllerMatch = /@Controller\s*\(\s*['"`]([^'"`]*)['"`]\s*\)/.exec(input.code);
|
|
80
|
+
const basePath = controllerMatch ? controllerMatch[1] : '';
|
|
81
|
+
// Validate each found endpoint
|
|
82
|
+
for (const found of foundEndpoints) {
|
|
83
|
+
// Reconstruct full path
|
|
84
|
+
const fullPath = basePath
|
|
85
|
+
? `/${basePath}/${found.path}`.replace(/\/+/g, '/').replace(/\/$/, '')
|
|
86
|
+
: found.path;
|
|
87
|
+
// Normalize path: convert NestJS :param to schema :param format
|
|
88
|
+
const normalizedPath = fullPath.replace(/:(\w+)/g, ':$1');
|
|
89
|
+
// Find matching endpoint in schema
|
|
90
|
+
const schemaEndpoint = schema.endpoints.find((ep) => ep.method === found.method && normalizePath(ep.path) === normalizePath(normalizedPath));
|
|
91
|
+
if (!schemaEndpoint) {
|
|
92
|
+
// Check if it's a valid endpoint but wrong method
|
|
93
|
+
const samePathEndpoint = schema.endpoints.find((ep) => normalizePath(ep.path) === normalizePath(normalizedPath));
|
|
94
|
+
if (samePathEndpoint) {
|
|
95
|
+
errors.push({
|
|
96
|
+
type: 'WRONG_METHOD',
|
|
97
|
+
message: `Line ${found.line}: ${found.method} ${normalizedPath} uses wrong HTTP method`,
|
|
98
|
+
suggestion: `Correct method is ${samePathEndpoint.method} ${samePathEndpoint.path}`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
const validEndpoints = schema.endpoints
|
|
103
|
+
.filter((ep) => ep.method === found.method)
|
|
104
|
+
.map((ep) => `${ep.method} ${ep.path}`);
|
|
105
|
+
errors.push({
|
|
106
|
+
type: 'UNKNOWN_ENDPOINT',
|
|
107
|
+
message: `Line ${found.line}: ${found.method} ${normalizedPath} does not exist in the ${input.resource} API`,
|
|
108
|
+
suggestion: `Valid ${found.method} endpoints: ${validEndpoints.join(', ') || 'none'}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
// Check scope access
|
|
114
|
+
if (!allowedEndpointKeys.has(`${schemaEndpoint.method} ${schemaEndpoint.path}`)) {
|
|
115
|
+
errors.push({
|
|
116
|
+
type: 'SCOPE_MISMATCH',
|
|
117
|
+
message: `${schemaEndpoint.handler_name} requires ${schemaEndpoint.required_scope} scope but app only has [${input.scopes.join(', ')}]`,
|
|
118
|
+
suggestion: `Remove ${schemaEndpoint.handler_name} endpoint or request ${schemaEndpoint.required_scope} scope`,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Check handler name
|
|
122
|
+
if (found.handlerName && found.handlerName !== schemaEndpoint.handler_name) {
|
|
123
|
+
errors.push({
|
|
124
|
+
type: 'WRONG_HANDLER_NAME',
|
|
125
|
+
message: `Line ${found.line}: Handler "${found.handlerName}" should be "${schemaEndpoint.handler_name}"`,
|
|
126
|
+
suggestion: `Rename to "${schemaEndpoint.handler_name}" to match the API convention`,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Check endpoint ordering
|
|
131
|
+
const orderedEndpoints = foundEndpoints
|
|
132
|
+
.map((found) => {
|
|
133
|
+
const fullPath = basePath
|
|
134
|
+
? `/${basePath}/${found.path}`.replace(/\/+/g, '/').replace(/\/$/, '')
|
|
135
|
+
: found.path;
|
|
136
|
+
const normalizedPath = fullPath.replace(/:(\w+)/g, ':$1');
|
|
137
|
+
const schemaEp = schema.endpoints.find((ep) => ep.method === found.method && normalizePath(ep.path) === normalizePath(normalizedPath));
|
|
138
|
+
return schemaEp ? { ...found, controller_order: schemaEp.controller_order, schema_handler: schemaEp.handler_name } : null;
|
|
139
|
+
})
|
|
140
|
+
.filter(Boolean);
|
|
141
|
+
for (let i = 1; i < orderedEndpoints.length; i++) {
|
|
142
|
+
if (orderedEndpoints[i].controller_order < orderedEndpoints[i - 1].controller_order) {
|
|
143
|
+
errors.push({
|
|
144
|
+
type: 'WRONG_ORDER',
|
|
145
|
+
message: `${orderedEndpoints[i].schema_handler} (order: ${orderedEndpoints[i].controller_order}) appears before ${orderedEndpoints[i - 1].schema_handler} (order: ${orderedEndpoints[i - 1].controller_order})`,
|
|
146
|
+
suggestion: `Endpoints must follow controller_order: ${allowedEndpoints.sort((a, b) => a.controller_order - b.controller_order).map((e) => e.handler_name).join(' → ')}`,
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Check for missing endpoints (that the scopes would allow)
|
|
151
|
+
for (const allowed of allowedEndpoints) {
|
|
152
|
+
const found = foundEndpoints.some((f) => {
|
|
153
|
+
const fullPath = basePath
|
|
154
|
+
? `/${basePath}/${f.path}`.replace(/\/+/g, '/').replace(/\/$/, '')
|
|
155
|
+
: f.path;
|
|
156
|
+
return f.method === allowed.method && normalizePath(fullPath) === normalizePath(allowed.path);
|
|
157
|
+
});
|
|
158
|
+
if (!found) {
|
|
159
|
+
errors.push({
|
|
160
|
+
type: 'MISSING_ENDPOINT',
|
|
161
|
+
message: `Missing endpoint: ${allowed.method} ${allowed.path} (${allowed.handler_name})`,
|
|
162
|
+
suggestion: `Add ${allowed.handler_name} handler with @${capitalize(allowed.method.toLowerCase())}() decorator`,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
valid: errors.length === 0,
|
|
168
|
+
errors,
|
|
169
|
+
endpoints_validated: foundEndpoints.length,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Normalize a path for comparison (remove leading/trailing slashes, normalize params)
|
|
174
|
+
*/
|
|
175
|
+
function normalizePath(path) {
|
|
176
|
+
return path
|
|
177
|
+
.replace(/^\/+|\/+$/g, '')
|
|
178
|
+
.replace(/\{(\w+)\}/g, ':$1') // Convert {id} to :id
|
|
179
|
+
.replace(/:(\w+)/g, ':$1')
|
|
180
|
+
.toLowerCase();
|
|
181
|
+
}
|
|
182
|
+
function capitalize(s) {
|
|
183
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=validate-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate-code.js","sourceRoot":"","sources":["../../src/tools/validate-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger that writes to BOTH stderr (for MCP protocol) AND a persistent log file.
|
|
3
|
+
* The log file is stored in the mcp-v2 root so you can review the full flow after testing.
|
|
4
|
+
*/
|
|
5
|
+
declare const LOG_FILE: string;
|
|
6
|
+
export declare const logger: {
|
|
7
|
+
info: (message: string, ...args: unknown[]) => void;
|
|
8
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
9
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
10
|
+
debug: (message: string, ...args: unknown[]) => void;
|
|
11
|
+
toolCall: (toolName: string, input: unknown) => void;
|
|
12
|
+
toolResult: (toolName: string, durationMs: number, result: unknown) => void;
|
|
13
|
+
toolError: (toolName: string, durationMs: number, error: unknown) => void;
|
|
14
|
+
};
|
|
15
|
+
export { LOG_FILE };
|
|
16
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,QAAA,MAAM,QAAQ,QAAoC,CAAC;AAiCnD,eAAO,MAAM,MAAM;oBACD,MAAM,WAAW,OAAO,EAAE;oBAK1B,MAAM,WAAW,OAAO,EAAE;qBAKzB,MAAM,WAAW,OAAO,EAAE;qBAK1B,MAAM,WAAW,OAAO,EAAE;yBAQtB,MAAM,SAAS,OAAO;2BAMpB,MAAM,cAAc,MAAM,UAAU,OAAO;0BAM5C,MAAM,cAAc,MAAM,SAAS,OAAO;CAOjE,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logger that writes to BOTH stderr (for MCP protocol) AND a persistent log file.
|
|
3
|
+
* The log file is stored in the mcp-v2 root so you can review the full flow after testing.
|
|
4
|
+
*/
|
|
5
|
+
import { appendFileSync, existsSync, mkdirSync } from 'fs';
|
|
6
|
+
import { join, resolve, dirname } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
// Log file lives in ratio-mcp-v2/logs/docs-server.log
|
|
11
|
+
const LOGS_DIR = resolve(__dirname, '..', '..', '..', '..', 'logs');
|
|
12
|
+
const LOG_FILE = join(LOGS_DIR, 'docs-server.log');
|
|
13
|
+
try {
|
|
14
|
+
if (!existsSync(LOGS_DIR)) {
|
|
15
|
+
mkdirSync(LOGS_DIR, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
catch { /* ignore */ }
|
|
19
|
+
function timestamp() {
|
|
20
|
+
return new Date().toISOString();
|
|
21
|
+
}
|
|
22
|
+
function writeToFile(line) {
|
|
23
|
+
try {
|
|
24
|
+
if (!existsSync(LOGS_DIR)) {
|
|
25
|
+
mkdirSync(LOGS_DIR, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
appendFileSync(LOG_FILE, line + '\n', 'utf-8');
|
|
28
|
+
}
|
|
29
|
+
catch { /* swallow */ }
|
|
30
|
+
}
|
|
31
|
+
function safeStringify(obj, maxLen = 4000) {
|
|
32
|
+
try {
|
|
33
|
+
const str = JSON.stringify(obj);
|
|
34
|
+
if (str && str.length > maxLen) {
|
|
35
|
+
return str.substring(0, maxLen) + `...[truncated, total ${str.length} chars]`;
|
|
36
|
+
}
|
|
37
|
+
return str || '';
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return String(obj);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export const logger = {
|
|
44
|
+
info: (message, ...args) => {
|
|
45
|
+
const line = `[ratio-docs] ${timestamp()} INFO: ${message}${args.length ? ' ' + args.map(a => safeStringify(a)).join(' ') : ''}`;
|
|
46
|
+
console.error(line);
|
|
47
|
+
writeToFile(line);
|
|
48
|
+
},
|
|
49
|
+
warn: (message, ...args) => {
|
|
50
|
+
const line = `[ratio-docs] ${timestamp()} WARN: ${message}${args.length ? ' ' + args.map(a => safeStringify(a)).join(' ') : ''}`;
|
|
51
|
+
console.error(line);
|
|
52
|
+
writeToFile(line);
|
|
53
|
+
},
|
|
54
|
+
error: (message, ...args) => {
|
|
55
|
+
const line = `[ratio-docs] ${timestamp()} ERROR: ${message}${args.length ? ' ' + args.map(a => safeStringify(a)).join(' ') : ''}`;
|
|
56
|
+
console.error(line);
|
|
57
|
+
writeToFile(line);
|
|
58
|
+
},
|
|
59
|
+
debug: (message, ...args) => {
|
|
60
|
+
const line = `[ratio-docs] ${timestamp()} DEBUG: ${message}${args.length ? ' ' + args.map(a => safeStringify(a)).join(' ') : ''}`;
|
|
61
|
+
if (process.env.DEBUG) {
|
|
62
|
+
console.error(line);
|
|
63
|
+
}
|
|
64
|
+
writeToFile(line);
|
|
65
|
+
},
|
|
66
|
+
toolCall: (toolName, input) => {
|
|
67
|
+
const line = `[ratio-docs] ${timestamp()} TOOL_CALL: ▶ ${toolName} | input: ${safeStringify(input)}`;
|
|
68
|
+
console.error(line);
|
|
69
|
+
writeToFile(line);
|
|
70
|
+
},
|
|
71
|
+
toolResult: (toolName, durationMs, result) => {
|
|
72
|
+
const line = `[ratio-docs] ${timestamp()} TOOL_RESULT: ✓ ${toolName} | ${durationMs}ms | output: ${safeStringify(result)}`;
|
|
73
|
+
console.error(line);
|
|
74
|
+
writeToFile(line);
|
|
75
|
+
},
|
|
76
|
+
toolError: (toolName, durationMs, error) => {
|
|
77
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
78
|
+
const stack = error instanceof Error ? error.stack : '';
|
|
79
|
+
const line = `[ratio-docs] ${timestamp()} TOOL_ERROR: ✗ ${toolName} | ${durationMs}ms | error: ${message}${stack ? `\n STACK: ${stack}` : ''}`;
|
|
80
|
+
console.error(line);
|
|
81
|
+
writeToFile(line);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
export { LOG_FILE };
|
|
85
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ResourceSchema, WebhooksSchema, OAuthSchema } from '@ratio-mcp-qa/shared';
|
|
2
|
+
export declare function loadResourceSchema(resource: string): ResourceSchema;
|
|
3
|
+
export declare function loadWebhooks(): WebhooksSchema;
|
|
4
|
+
export declare function loadOAuth(): OAuthSchema;
|
|
5
|
+
/**
|
|
6
|
+
* Get list of available resource schema files (excludes oauth.json and webhooks.json)
|
|
7
|
+
*/
|
|
8
|
+
export declare function getAvailableResourceFiles(): string[];
|
|
9
|
+
/**
|
|
10
|
+
* Clear the cache (useful for testing)
|
|
11
|
+
*/
|
|
12
|
+
export declare function clearCache(): void;
|
|
13
|
+
//# sourceMappingURL=schema-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-loader.d.ts","sourceRoot":"","sources":["../../src/utils/schema-loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAgCxF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAEnE;AAED,wBAAgB,YAAY,IAAI,cAAc,CAE7C;AAED,wBAAgB,SAAS,IAAI,WAAW,CAEvC;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CASpD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
|