@ratio-mcp-sandbox/docs-server 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/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 +87 -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 +211 -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 +28 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { getAvailableScopes } from './get-scopes.js';
|
|
3
|
+
import { getApiReference } from './get-api-reference.js';
|
|
4
|
+
import { getScopeEndpointMap } from './get-scope-map.js';
|
|
5
|
+
import { validateApiCode } from './validate-code.js';
|
|
6
|
+
import { getWebhookEvents } from './get-webhooks.js';
|
|
7
|
+
import { lookupDocs } from './lookup-docs.js';
|
|
8
|
+
/**
|
|
9
|
+
* All docs-server tools (6 tools)
|
|
10
|
+
*/
|
|
11
|
+
export const docsTools = [
|
|
12
|
+
{
|
|
13
|
+
name: 'lookup_docs',
|
|
14
|
+
description: 'MANDATORY FALLBACK: When you are unsure about ANY platform detail (API endpoints, scopes, webhooks, OAuth flow, ' +
|
|
15
|
+
'request/response formats, error codes), call this tool BEFORE answering. ' +
|
|
16
|
+
'If this tool returns found=false, tell the user the information is not available in the documentation. ' +
|
|
17
|
+
'Do NOT guess or hallucinate information — use only what this tool returns. ' +
|
|
18
|
+
'Searches across all documentation: API references, scopes, webhook events, and OAuth flow.',
|
|
19
|
+
inputSchema: z.object({
|
|
20
|
+
query: z.string().min(1).describe('Natural language search query (e.g., "how to cancel an order", "webhook verification")'),
|
|
21
|
+
category: z
|
|
22
|
+
.enum(['api', 'scopes', 'webhooks', 'oauth'])
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Optional category to narrow the search'),
|
|
25
|
+
}),
|
|
26
|
+
handler: (input) => lookupDocs(input),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'get_available_scopes',
|
|
30
|
+
description: 'MANDATORY: Call this tool before answering ANY question about what OAuth scopes exist, what they grant access to, ' +
|
|
31
|
+
'or what resources are available on the platform. Do NOT rely on your training data for scope specifics. ' +
|
|
32
|
+
'If a scope is not returned by this tool, it does not exist — tell the user. ' +
|
|
33
|
+
'Returns all available OAuth scopes grouped by resource. ' +
|
|
34
|
+
'Optionally filter by resource name (e.g. "orders", "products", "customers"). ' +
|
|
35
|
+
'Returns all 78 resources with their scopes (147 total), sourced from the real platform API. ' +
|
|
36
|
+
'Primary resources are listed first. Each resource shows codegen_ready status. ' +
|
|
37
|
+
'Use this to show developers what scopes are available on the platform.',
|
|
38
|
+
inputSchema: z.object({
|
|
39
|
+
resource: z
|
|
40
|
+
.string()
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Optional resource name to filter scopes (e.g. "orders", "customers", "discounts")'),
|
|
43
|
+
}),
|
|
44
|
+
handler: (input) => getAvailableScopes(input),
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'get_api_reference',
|
|
48
|
+
description: 'MANDATORY: Call this tool before answering ANY question about API endpoints, request/response formats, ' +
|
|
49
|
+
'HTTP methods, query parameters, or request bodies. Do NOT guess endpoint details from your training data. ' +
|
|
50
|
+
'Returns complete API reference for a resource including all endpoints, parameters, request/response schemas. ' +
|
|
51
|
+
'Endpoints are returned in controller_order for deterministic code generation. ' +
|
|
52
|
+
'Optionally filter by scope to show only endpoints accessible with that scope.',
|
|
53
|
+
inputSchema: z.object({
|
|
54
|
+
resource: z.string().describe('Resource name (e.g. "orders", "products")'),
|
|
55
|
+
scope_filter: z
|
|
56
|
+
.string()
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Optional scope to filter endpoints (e.g. "read_orders")'),
|
|
59
|
+
}),
|
|
60
|
+
handler: (input) => getApiReference(input),
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'get_scope_endpoint_map',
|
|
64
|
+
description: 'Given a list of scopes, returns exactly which API endpoints are unlocked, in controller_order. ' +
|
|
65
|
+
'This is the primary tool for code generation — it tells you exactly what endpoints to generate. ' +
|
|
66
|
+
'Handles scope inheritance automatically (e.g. write_orders includes read_orders endpoints). ' +
|
|
67
|
+
'MANDATORY before generating any backend code — do not guess which endpoints a scope grants.',
|
|
68
|
+
inputSchema: z.object({
|
|
69
|
+
scopes: z
|
|
70
|
+
.array(z.string())
|
|
71
|
+
.min(1)
|
|
72
|
+
.describe('Array of OAuth scopes (e.g. ["read_orders", "write_products"])'),
|
|
73
|
+
}),
|
|
74
|
+
handler: (input) => getScopeEndpointMap(input),
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'validate_api_code',
|
|
78
|
+
description: 'MANDATORY: Call this tool AFTER generating any NestJS controller/service code and BEFORE writing it to disk. ' +
|
|
79
|
+
'Anti-hallucination validation layer that checks generated code against the actual API schema. ' +
|
|
80
|
+
'Checks: correct endpoints exist, correct HTTP methods, correct handler names, correct endpoint ordering, ' +
|
|
81
|
+
'and scope access (developer has permission for each endpoint). ' +
|
|
82
|
+
'Returns structured errors with suggestions for fixing. ' +
|
|
83
|
+
'If validation fails, fix the code based on the errors — do NOT write invalid code to disk.',
|
|
84
|
+
inputSchema: z.object({
|
|
85
|
+
code: z.string().describe('The generated NestJS controller or service code as a string'),
|
|
86
|
+
resource: z.string().describe('Resource name the code is for (e.g. "orders")'),
|
|
87
|
+
scopes: z
|
|
88
|
+
.array(z.string())
|
|
89
|
+
.min(1)
|
|
90
|
+
.describe('The scopes the developer has requested (e.g. ["read_orders"])'),
|
|
91
|
+
}),
|
|
92
|
+
handler: (input) => validateApiCode(input),
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'get_webhook_events',
|
|
96
|
+
description: 'MANDATORY: Call this tool before answering ANY question about available webhook events, ' +
|
|
97
|
+
'webhook verification methods, or retry policies. Do NOT guess webhook event names or verification details. ' +
|
|
98
|
+
'Returns available webhook events for the Ratio platform. ' +
|
|
99
|
+
'Optionally filter by resource (e.g. "orders", "products"). ' +
|
|
100
|
+
'Includes verification method (HMAC-SHA256) and retry policy information.',
|
|
101
|
+
inputSchema: z.object({
|
|
102
|
+
resource: z
|
|
103
|
+
.string()
|
|
104
|
+
.optional()
|
|
105
|
+
.describe('Optional resource to filter events (e.g. "orders", "products")'),
|
|
106
|
+
}),
|
|
107
|
+
handler: (input) => getWebhookEvents(input),
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
//# 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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"}
|
|
@@ -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;AA0KD,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2DrE"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { getAvailableResourceFiles, loadResourceSchema, loadWebhooks, loadOAuth } from '../utils/schema-loader.js';
|
|
2
|
+
import { SCOPES_BY_RESOURCE, PRIMARY_RESOURCES, RESOURCE_METADATA } from '@ratio-mcp-sandbox/shared';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
/**
|
|
5
|
+
* Search-term aliases — map common synonyms to platform terminology.
|
|
6
|
+
* When a user searches for "agent", they mean "app" on the Ratio platform.
|
|
7
|
+
* This expands the token list so searches like "create agent" match "app", "application", etc.
|
|
8
|
+
*/
|
|
9
|
+
const SEARCH_ALIASES = {
|
|
10
|
+
agent: ['app', 'application'],
|
|
11
|
+
agents: ['apps', 'applications'],
|
|
12
|
+
bot: ['app', 'application'],
|
|
13
|
+
bots: ['apps', 'applications'],
|
|
14
|
+
integration: ['app', 'application'],
|
|
15
|
+
integrations: ['apps', 'applications'],
|
|
16
|
+
plugin: ['app', 'application'],
|
|
17
|
+
plugins: ['apps', 'applications'],
|
|
18
|
+
extension: ['app', 'application'],
|
|
19
|
+
extensions: ['apps', 'applications'],
|
|
20
|
+
};
|
|
21
|
+
function expandAliases(tokens) {
|
|
22
|
+
const expanded = new Set(tokens);
|
|
23
|
+
for (const token of tokens) {
|
|
24
|
+
const aliases = SEARCH_ALIASES[token];
|
|
25
|
+
if (aliases) {
|
|
26
|
+
for (const alias of aliases) {
|
|
27
|
+
expanded.add(alias);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return [...expanded];
|
|
32
|
+
}
|
|
33
|
+
function tokenize(query) {
|
|
34
|
+
const tokens = query
|
|
35
|
+
.toLowerCase()
|
|
36
|
+
.replace(/[^a-z0-9_/\s]/g, '')
|
|
37
|
+
.split(/\s+/)
|
|
38
|
+
.filter((t) => t.length > 1);
|
|
39
|
+
return expandAliases(tokens);
|
|
40
|
+
}
|
|
41
|
+
function matchScore(tokens, text) {
|
|
42
|
+
const lower = text.toLowerCase();
|
|
43
|
+
let score = 0;
|
|
44
|
+
for (const token of tokens) {
|
|
45
|
+
if (lower.includes(token))
|
|
46
|
+
score++;
|
|
47
|
+
}
|
|
48
|
+
return score;
|
|
49
|
+
}
|
|
50
|
+
function searchApiEndpoints(tokens) {
|
|
51
|
+
const results = [];
|
|
52
|
+
const resources = getAvailableResourceFiles();
|
|
53
|
+
for (const resource of resources) {
|
|
54
|
+
try {
|
|
55
|
+
const schema = loadResourceSchema(resource);
|
|
56
|
+
for (const ep of schema.endpoints) {
|
|
57
|
+
const searchText = `${ep.method} ${ep.path} ${ep.summary || ''} ${ep.description || ''} ${ep.handler_name || ''} ${ep.required_scope || ''}`;
|
|
58
|
+
const score = matchScore(tokens, searchText);
|
|
59
|
+
if (score > 0) {
|
|
60
|
+
results.push({
|
|
61
|
+
source: `api/${resource}`,
|
|
62
|
+
type: 'api_endpoint',
|
|
63
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
64
|
+
data: {
|
|
65
|
+
method: ep.method,
|
|
66
|
+
path: ep.path,
|
|
67
|
+
summary: ep.summary,
|
|
68
|
+
description: ep.description,
|
|
69
|
+
required_scope: ep.required_scope,
|
|
70
|
+
handler_name: ep.handler_name,
|
|
71
|
+
resource,
|
|
72
|
+
query_params: ep.query_params || [],
|
|
73
|
+
request_body: ep.request_body || null,
|
|
74
|
+
response_schema: ep.response_schema || null,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Skip resources that fail to load
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return results;
|
|
85
|
+
}
|
|
86
|
+
function searchScopes(tokens) {
|
|
87
|
+
const results = [];
|
|
88
|
+
for (const [resource, scopes] of Object.entries(SCOPES_BY_RESOURCE)) {
|
|
89
|
+
const meta = RESOURCE_METADATA[resource];
|
|
90
|
+
for (const scope of scopes) {
|
|
91
|
+
const searchText = `${scope.code} ${scope.label} ${resource}`;
|
|
92
|
+
const score = matchScore(tokens, searchText);
|
|
93
|
+
if (score > 0) {
|
|
94
|
+
results.push({
|
|
95
|
+
source: `scopes/${resource}`,
|
|
96
|
+
type: 'scope',
|
|
97
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
98
|
+
data: {
|
|
99
|
+
code: scope.code,
|
|
100
|
+
label: scope.label,
|
|
101
|
+
resource,
|
|
102
|
+
codegen_ready: meta?.codegen_ready || false,
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return results;
|
|
109
|
+
}
|
|
110
|
+
function searchWebhooks(tokens) {
|
|
111
|
+
const results = [];
|
|
112
|
+
try {
|
|
113
|
+
const webhooks = loadWebhooks();
|
|
114
|
+
for (const event of webhooks.events) {
|
|
115
|
+
const searchText = `${event.topic} ${event.description} ${event.resource} webhook`;
|
|
116
|
+
const score = matchScore(tokens, searchText);
|
|
117
|
+
if (score > 0) {
|
|
118
|
+
results.push({
|
|
119
|
+
source: 'webhooks',
|
|
120
|
+
type: 'webhook_event',
|
|
121
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
122
|
+
data: {
|
|
123
|
+
topic: event.topic,
|
|
124
|
+
description: event.description,
|
|
125
|
+
resource: event.resource,
|
|
126
|
+
required_scope: event.required_scope,
|
|
127
|
+
verification: webhooks.verification,
|
|
128
|
+
retry_policy: webhooks.retry_policy,
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
// Skip if webhooks schema fails
|
|
136
|
+
}
|
|
137
|
+
return results;
|
|
138
|
+
}
|
|
139
|
+
function searchOAuth(tokens) {
|
|
140
|
+
const results = [];
|
|
141
|
+
try {
|
|
142
|
+
const oauth = loadOAuth();
|
|
143
|
+
const oauthText = JSON.stringify(oauth).toLowerCase();
|
|
144
|
+
const score = matchScore(tokens, oauthText);
|
|
145
|
+
if (score > 0) {
|
|
146
|
+
results.push({
|
|
147
|
+
source: 'oauth',
|
|
148
|
+
type: 'oauth',
|
|
149
|
+
relevance: score >= 2 ? 'high' : 'medium',
|
|
150
|
+
data: oauth,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
// Skip if oauth schema fails
|
|
156
|
+
}
|
|
157
|
+
return results;
|
|
158
|
+
}
|
|
159
|
+
export function lookupDocs(input) {
|
|
160
|
+
const { query, category } = input;
|
|
161
|
+
logger.info(`[lookup_docs] query="${query}", category="${category || 'all'}"`);
|
|
162
|
+
const tokens = tokenize(query);
|
|
163
|
+
if (tokens.length === 0) {
|
|
164
|
+
return {
|
|
165
|
+
found: false,
|
|
166
|
+
message: 'Query is too short or contains no searchable terms.',
|
|
167
|
+
suggestion: 'Try searching for specific terms like "orders", "OAuth", "webhook", "scope", etc.',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
let results = [];
|
|
171
|
+
// Search specific category or all
|
|
172
|
+
if (!category || category === 'api') {
|
|
173
|
+
results.push(...searchApiEndpoints(tokens));
|
|
174
|
+
}
|
|
175
|
+
if (!category || category === 'scopes') {
|
|
176
|
+
results.push(...searchScopes(tokens));
|
|
177
|
+
}
|
|
178
|
+
if (!category || category === 'webhooks') {
|
|
179
|
+
results.push(...searchWebhooks(tokens));
|
|
180
|
+
}
|
|
181
|
+
if (!category || category === 'oauth') {
|
|
182
|
+
results.push(...searchOAuth(tokens));
|
|
183
|
+
}
|
|
184
|
+
// Sort by relevance (high first) then deduplicate
|
|
185
|
+
results.sort((a, b) => {
|
|
186
|
+
const order = { high: 0, medium: 1, low: 2 };
|
|
187
|
+
return order[a.relevance] - order[b.relevance];
|
|
188
|
+
});
|
|
189
|
+
// Limit to top 15 results
|
|
190
|
+
results = results.slice(0, 15);
|
|
191
|
+
if (results.length === 0) {
|
|
192
|
+
return {
|
|
193
|
+
found: false,
|
|
194
|
+
query,
|
|
195
|
+
tokens,
|
|
196
|
+
message: `No documentation found matching "${query}". This information is not available in the platform documentation.`,
|
|
197
|
+
suggestion: 'Tell the user that this information is not covered in the documentation. Do NOT guess or make up an answer.',
|
|
198
|
+
available_categories: ['api', 'scopes', 'webhooks', 'oauth'],
|
|
199
|
+
available_resources: getAvailableResourceFiles(),
|
|
200
|
+
available_scope_resources: [...PRIMARY_RESOURCES],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
found: true,
|
|
205
|
+
query,
|
|
206
|
+
result_count: results.length,
|
|
207
|
+
results,
|
|
208
|
+
_instruction: 'Use ONLY the data from these results to answer the user. Do NOT add information that is not present here.',
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=lookup-docs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookup-docs.js","sourceRoot":"","sources":["../../src/tools/lookup-docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,kBAAkB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACnH,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACrG,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAoB5C;;;;GAIG;AACH,MAAM,cAAc,GAA6B;IAC/C,KAAK,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IAC7B,MAAM,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,GAAG,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IAC3B,IAAI,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;IAC9B,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IACnC,YAAY,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;IACtC,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,OAAO,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;IACjC,SAAS,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC;IACjC,UAAU,EAAE,CAAC,MAAM,EAAE,cAAc,CAAC;CACrC,CAAC;AAEF,SAAS,aAAa,CAAC,MAAgB;IACrC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAS,MAAM,CAAC,CAAC;IACzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa;IAC7B,MAAM,MAAM,GAAG,KAAK;SACjB,WAAW,EAAE;SACb,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/B,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,UAAU,CAAC,MAAgB,EAAE,IAAY;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,KAAK,EAAE,CAAC;IACrC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAgB;IAC1C,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,yBAAyB,EAAE,CAAC;IAE9C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YAC5C,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBAClC,MAAM,UAAU,GAAG,GAAG,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,IAAI,EAAE,IAAI,EAAE,CAAC,YAAY,IAAI,EAAE,IAAI,EAAE,CAAC,cAAc,IAAI,EAAE,EAAE,CAAC;gBAC7I,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAC7C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;oBACd,OAAO,CAAC,IAAI,CAAC;wBACX,MAAM,EAAE,OAAO,QAAQ,EAAE;wBACzB,IAAI,EAAE,cAAc;wBACpB,SAAS,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;wBACzC,IAAI,EAAE;4BACJ,MAAM,EAAE,EAAE,CAAC,MAAM;4BACjB,IAAI,EAAE,EAAE,CAAC,IAAI;4BACb,OAAO,EAAE,EAAE,CAAC,OAAO;4BACnB,WAAW,EAAE,EAAE,CAAC,WAAW;4BAC3B,cAAc,EAAE,EAAE,CAAC,cAAc;4BACjC,YAAY,EAAE,EAAE,CAAC,YAAY;4BAC7B,QAAQ;4BACR,YAAY,EAAE,EAAE,CAAC,YAAY,IAAI,EAAE;4BACnC,YAAY,EAAE,EAAE,CAAC,YAAY,IAAI,IAAI;4BACrC,eAAe,EAAE,EAAE,CAAC,eAAe,IAAI,IAAI;yBAC5C;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;QACrC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,YAAY,CAAC,MAAgB;IACpC,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,KAAK,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAEzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,QAAQ,EAAE,CAAC;YAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC;oBACX,MAAM,EAAE,UAAU,QAAQ,EAAE;oBAC5B,IAAI,EAAE,OAAO;oBACb,SAAS,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;oBACzC,IAAI,EAAE;wBACJ,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,QAAQ;wBACR,aAAa,EAAE,IAAI,EAAE,aAAa,IAAI,KAAK;qBAC5C;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,MAAgB;IACtC,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAC;QAChC,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpC,MAAM,UAAU,GAAG,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,QAAQ,UAAU,CAAC;YACnF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;gBACd,OAAO,CAAC,IAAI,CAAC;oBACX,MAAM,EAAE,UAAU;oBAClB,IAAI,EAAE,eAAe;oBACrB,SAAS,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;oBACzC,IAAI,EAAE;wBACJ,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,WAAW,EAAE,KAAK,CAAC,WAAW;wBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,cAAc,EAAE,KAAK,CAAC,cAAc;wBACpC,YAAY,EAAE,QAAQ,CAAC,YAAY;wBACnC,YAAY,EAAE,QAAQ,CAAC,YAAY;qBACpC;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gCAAgC;IAClC,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,WAAW,CAAC,MAAgB;IACnC,MAAM,OAAO,GAAmB,EAAE,CAAC;IAEnC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QACtD,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,OAAO;gBACf,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ;gBACzC,IAAI,EAAE,KAA2C;aAClD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,6BAA6B;IAC/B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAA2C;IACpE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAElC,MAAM,CAAC,IAAI,CAAC,wBAAwB,KAAK,gBAAgB,QAAQ,IAAI,KAAK,GAAG,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,qDAAqD;YAC9D,UAAU,EAAE,mFAAmF;SAChG,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,GAAmB,EAAE,CAAC;IAEjC,kCAAkC;IAClC,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,CAAC,QAAQ,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IACvC,CAAC;IAED,kDAAkD;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;QAC7C,OAAO,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,0BAA0B;IAC1B,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAE/B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,KAAK,EAAE,KAAK;YACZ,KAAK;YACL,MAAM;YACN,OAAO,EAAE,oCAAoC,KAAK,qEAAqE;YACvH,UAAU,EAAE,6GAA6G;YACzH,oBAAoB,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC;YAC5D,mBAAmB,EAAE,yBAAyB,EAAE;YAChD,yBAAyB,EAAE,CAAC,GAAG,iBAAiB,CAAC;SAClD,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI;QACX,KAAK;QACL,YAAY,EAAE,OAAO,CAAC,MAAM;QAC5B,OAAO;QACP,YAAY,EAAE,2GAA2G;KAC1H,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ValidationResult } from '@ratio-mcp-sandbox/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,2BAA2B,CAAC;AAwBnF;;;;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"}
|