@ratio-mcp/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/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 +73 -0
- package/dist/tools/get-scopes.d.ts.map +1 -0
- package/dist/tools/get-scopes.js +74 -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 +85 -0
- package/dist/tools/index.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 +17 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +52 -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,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,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logger that writes to stderr (MCP servers use stdout for protocol messages).
|
|
3
|
+
* Timestamps included for tracing tool execution duration.
|
|
4
|
+
*/
|
|
5
|
+
export declare const logger: {
|
|
6
|
+
info: (message: string, ...args: unknown[]) => void;
|
|
7
|
+
warn: (message: string, ...args: unknown[]) => void;
|
|
8
|
+
error: (message: string, ...args: unknown[]) => void;
|
|
9
|
+
debug: (message: string, ...args: unknown[]) => void;
|
|
10
|
+
/** Log an incoming tool call with its input parameters */
|
|
11
|
+
toolCall: (toolName: string, input: unknown) => void;
|
|
12
|
+
/** Log a successful tool result */
|
|
13
|
+
toolResult: (toolName: string, durationMs: number, result: unknown) => void;
|
|
14
|
+
/** Log a failed tool execution */
|
|
15
|
+
toolError: (toolName: string, durationMs: number, error: unknown) => void;
|
|
16
|
+
};
|
|
17
|
+
//# 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;AAqBH,eAAO,MAAM,MAAM;oBACD,MAAM,WAAW,OAAO,EAAE;oBAG1B,MAAM,WAAW,OAAO,EAAE;qBAGzB,MAAM,WAAW,OAAO,EAAE;qBAG1B,MAAM,WAAW,OAAO,EAAE;IAM3C,0DAA0D;yBACrC,MAAM,SAAS,OAAO;IAI3C,mCAAmC;2BACZ,MAAM,cAAc,MAAM,UAAU,OAAO;IAIlE,kCAAkC;0BACZ,MAAM,cAAc,MAAM,SAAS,OAAO;CAIjE,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple logger that writes to stderr (MCP servers use stdout for protocol messages).
|
|
3
|
+
* Timestamps included for tracing tool execution duration.
|
|
4
|
+
*/
|
|
5
|
+
function timestamp() {
|
|
6
|
+
return new Date().toISOString();
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Safely stringify objects for logging, truncating to maxLen to avoid flooding stderr.
|
|
10
|
+
*/
|
|
11
|
+
function safeStringify(obj, maxLen = 2000) {
|
|
12
|
+
try {
|
|
13
|
+
const str = JSON.stringify(obj);
|
|
14
|
+
if (str && str.length > maxLen) {
|
|
15
|
+
return str.substring(0, maxLen) + `...[truncated, total ${str.length} chars]`;
|
|
16
|
+
}
|
|
17
|
+
return str || '';
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return String(obj);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export const logger = {
|
|
24
|
+
info: (message, ...args) => {
|
|
25
|
+
console.error(`[ratio-docs] ${timestamp()} INFO: ${message}`, ...args);
|
|
26
|
+
},
|
|
27
|
+
warn: (message, ...args) => {
|
|
28
|
+
console.error(`[ratio-docs] ${timestamp()} WARN: ${message}`, ...args);
|
|
29
|
+
},
|
|
30
|
+
error: (message, ...args) => {
|
|
31
|
+
console.error(`[ratio-docs] ${timestamp()} ERROR: ${message}`, ...args);
|
|
32
|
+
},
|
|
33
|
+
debug: (message, ...args) => {
|
|
34
|
+
if (process.env.DEBUG) {
|
|
35
|
+
console.error(`[ratio-docs] DEBUG: ${message}`, ...args);
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
/** Log an incoming tool call with its input parameters */
|
|
39
|
+
toolCall: (toolName, input) => {
|
|
40
|
+
console.error(`[ratio-docs] ${timestamp()} TOOL_CALL: ▶ ${toolName} | input: ${safeStringify(input)}`);
|
|
41
|
+
},
|
|
42
|
+
/** Log a successful tool result */
|
|
43
|
+
toolResult: (toolName, durationMs, result) => {
|
|
44
|
+
console.error(`[ratio-docs] ${timestamp()} TOOL_RESULT: ✓ ${toolName} | ${durationMs}ms | output: ${safeStringify(result)}`);
|
|
45
|
+
},
|
|
46
|
+
/** Log a failed tool execution */
|
|
47
|
+
toolError: (toolName, durationMs, error) => {
|
|
48
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
|
+
console.error(`[ratio-docs] ${timestamp()} TOOL_ERROR: ✗ ${toolName} | ${durationMs}ms | error: ${message}`);
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,SAAS,SAAS;IAChB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,GAAY,EAAE,MAAM,GAAG,IAAI;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,GAAG,IAAI,GAAG,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;YAC/B,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,GAAG,wBAAwB,GAAG,CAAC,MAAM,SAAS,CAAC;QAChF,CAAC;QACD,OAAO,GAAG,IAAI,EAAE,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAE,EAAE;QAC5C,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,UAAU,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAE,EAAE;QAC5C,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,UAAU,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IACzE,CAAC;IACD,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAE,EAAE;QAC7C,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,WAAW,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;IAC1E,CAAC;IACD,KAAK,EAAE,CAAC,OAAe,EAAE,GAAG,IAAe,EAAE,EAAE;QAC7C,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,uBAAuB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,QAAQ,EAAE,CAAC,QAAgB,EAAE,KAAc,EAAE,EAAE;QAC7C,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,iBAAiB,QAAQ,aAAa,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzG,CAAC;IAED,mCAAmC;IACnC,UAAU,EAAE,CAAC,QAAgB,EAAE,UAAkB,EAAE,MAAe,EAAE,EAAE;QACpE,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,mBAAmB,QAAQ,MAAM,UAAU,gBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC/H,CAAC;IAED,kCAAkC;IAClC,SAAS,EAAE,CAAC,QAAgB,EAAE,UAAkB,EAAE,KAAc,EAAE,EAAE;QAClE,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,gBAAgB,SAAS,EAAE,kBAAkB,QAAQ,MAAM,UAAU,eAAe,OAAO,EAAE,CAAC,CAAC;IAC/G,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ResourceSchema, WebhooksSchema, OAuthSchema } from '@ratio-mcp/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,mBAAmB,CAAC;AAgCrF,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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync, readdirSync } from 'fs';
|
|
2
|
+
import { join, dirname } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { logger } from './logger.js';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
/**
|
|
8
|
+
* Path to schemas directory (relative to this file's location in dist/utils/)
|
|
9
|
+
*/
|
|
10
|
+
const SCHEMAS_DIR = join(__dirname, '..', 'schemas');
|
|
11
|
+
/**
|
|
12
|
+
* In-memory cache for loaded schemas
|
|
13
|
+
*/
|
|
14
|
+
const cache = new Map();
|
|
15
|
+
function loadJson(filename) {
|
|
16
|
+
const cached = cache.get(filename);
|
|
17
|
+
if (cached)
|
|
18
|
+
return cached;
|
|
19
|
+
const filePath = join(SCHEMAS_DIR, filename);
|
|
20
|
+
try {
|
|
21
|
+
const raw = readFileSync(filePath, 'utf-8');
|
|
22
|
+
const parsed = JSON.parse(raw);
|
|
23
|
+
cache.set(filename, parsed);
|
|
24
|
+
logger.debug(`Loaded schema: ${filename}`);
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
logger.error(`Failed to load schema: ${filename}`, err);
|
|
29
|
+
throw new Error(`Schema not found: ${filename}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function loadResourceSchema(resource) {
|
|
33
|
+
return loadJson(`${resource}.json`);
|
|
34
|
+
}
|
|
35
|
+
export function loadWebhooks() {
|
|
36
|
+
return loadJson('webhooks.json');
|
|
37
|
+
}
|
|
38
|
+
export function loadOAuth() {
|
|
39
|
+
return loadJson('oauth.json');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get list of available resource schema files (excludes oauth.json and webhooks.json)
|
|
43
|
+
*/
|
|
44
|
+
export function getAvailableResourceFiles() {
|
|
45
|
+
const EXCLUDED = ['oauth.json', 'webhooks.json'];
|
|
46
|
+
try {
|
|
47
|
+
return readdirSync(SCHEMAS_DIR)
|
|
48
|
+
.filter((f) => f.endsWith('.json') && !EXCLUDED.includes(f))
|
|
49
|
+
.map((f) => f.replace('.json', ''));
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Clear the cache (useful for testing)
|
|
57
|
+
*/
|
|
58
|
+
export function clearCache() {
|
|
59
|
+
cache.clear();
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=schema-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-loader.js","sourceRoot":"","sources":["../../src/utils/schema-loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;AAErD;;GAEG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmB,CAAC;AAEzC,SAAS,QAAQ,CAAI,QAAgB;IACnC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,MAAM;QAAE,OAAO,MAAW,CAAC;IAE/B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAM,CAAC;QACpC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC5B,MAAM,CAAC,KAAK,CAAC,kBAAkB,QAAQ,EAAE,CAAC,CAAC;QAC3C,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,0BAA0B,QAAQ,EAAE,EAAE,GAAG,CAAC,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,QAAQ,CAAiB,GAAG,QAAQ,OAAO,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAiB,eAAe,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,QAAQ,CAAc,YAAY,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,QAAQ,GAAG,CAAC,YAAY,EAAE,eAAe,CAAC,CAAC;IACjD,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,WAAW,CAAC;aAC5B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;aAC3D,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Simple Zod-to-JSON-Schema converter for MCP tool registration.
|
|
4
|
+
* Handles the common cases used in our tool definitions.
|
|
5
|
+
*/
|
|
6
|
+
export declare function zodToJsonSchema(schema: z.ZodType): Record<string, unknown>;
|
|
7
|
+
//# sourceMappingURL=zod-to-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-json.d.ts","sourceRoot":"","sources":["../../src/utils/zod-to-json.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE1E"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Simple Zod-to-JSON-Schema converter for MCP tool registration.
|
|
3
|
+
* Handles the common cases used in our tool definitions.
|
|
4
|
+
*/
|
|
5
|
+
export function zodToJsonSchema(schema) {
|
|
6
|
+
return convertZodType(schema);
|
|
7
|
+
}
|
|
8
|
+
function convertZodType(schema) {
|
|
9
|
+
const def = schema._def;
|
|
10
|
+
const typeName = def.typeName;
|
|
11
|
+
switch (typeName) {
|
|
12
|
+
case 'ZodObject': {
|
|
13
|
+
const shape = schema.shape;
|
|
14
|
+
const properties = {};
|
|
15
|
+
const required = [];
|
|
16
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
17
|
+
const fieldDef = value._def;
|
|
18
|
+
const isOptional = fieldDef.typeName === 'ZodOptional';
|
|
19
|
+
const innerType = isOptional ? fieldDef.innerType : value;
|
|
20
|
+
properties[key] = convertZodType(innerType);
|
|
21
|
+
// Add description from .describe()
|
|
22
|
+
const desc = fieldDef.description || innerType._def.description;
|
|
23
|
+
if (desc) {
|
|
24
|
+
properties[key].description = desc;
|
|
25
|
+
}
|
|
26
|
+
if (!isOptional) {
|
|
27
|
+
required.push(key);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const result = { type: 'object', properties };
|
|
31
|
+
if (required.length > 0)
|
|
32
|
+
result.required = required;
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
case 'ZodString':
|
|
36
|
+
return { type: 'string' };
|
|
37
|
+
case 'ZodNumber':
|
|
38
|
+
return { type: 'number' };
|
|
39
|
+
case 'ZodBoolean':
|
|
40
|
+
return { type: 'boolean' };
|
|
41
|
+
case 'ZodArray': {
|
|
42
|
+
const itemType = def.type || def.innerType;
|
|
43
|
+
return { type: 'array', items: convertZodType(itemType) };
|
|
44
|
+
}
|
|
45
|
+
case 'ZodEnum': {
|
|
46
|
+
const values = def.values;
|
|
47
|
+
return { type: 'string', enum: values };
|
|
48
|
+
}
|
|
49
|
+
case 'ZodOptional': {
|
|
50
|
+
const inner = def.innerType;
|
|
51
|
+
return convertZodType(inner);
|
|
52
|
+
}
|
|
53
|
+
case 'ZodDefault': {
|
|
54
|
+
const inner = def.innerType;
|
|
55
|
+
const result = convertZodType(inner);
|
|
56
|
+
result.default = def.defaultValue;
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
return { type: 'string' };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=zod-to-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zod-to-json.js","sourceRoot":"","sources":["../../src/utils/zod-to-json.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,cAAc,CAAC,MAAiB;IACvC,MAAM,GAAG,GAAI,MAAuD,CAAC,IAAI,CAAC;IAC1E,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAkB,CAAC;IAExC,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,MAAM,KAAK,GAAI,MAAiD,CAAC,KAAK,CAAC;YACvE,MAAM,UAAU,GAA4B,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;YAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,MAAM,QAAQ,GAAI,KAAsD,CAAC,IAAI,CAAC;gBAC9E,MAAM,UAAU,GAAG,QAAQ,CAAC,QAAQ,KAAK,aAAa,CAAC;gBACvD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAE,QAAQ,CAAC,SAAuB,CAAC,CAAC,CAAE,KAAmB,CAAC;gBAExF,UAAU,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;gBAE5C,mCAAmC;gBACnC,MAAM,IAAI,GAAI,QAAQ,CAAC,WAAsB,IAAM,SAA0D,CAAC,IAAI,CAAC,WAAsB,CAAC;gBAC1I,IAAI,IAAI,EAAE,CAAC;oBACR,UAAU,CAAC,GAAG,CAA6B,CAAC,WAAW,GAAG,IAAI,CAAC;gBAClE,CAAC;gBAED,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrB,CAAC;YACH,CAAC;YAED,MAAM,MAAM,GAA4B,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;YACvE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YACpD,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,KAAK,WAAW;YACd,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAE5B,KAAK,WAAW;YACd,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAE5B,KAAK,YAAY;YACf,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAE7B,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,QAAQ,GAAI,GAAG,CAAC,IAAkB,IAAK,GAAG,CAAC,SAAuB,CAAC;YACzE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5D,CAAC;QAED,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,MAAM,MAAM,GAAG,GAAG,CAAC,MAAkB,CAAC;YACtC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC1C,CAAC;QAED,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,KAAK,GAAG,GAAG,CAAC,SAAsB,CAAC;YACzC,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,MAAM,KAAK,GAAG,GAAG,CAAC,SAAsB,CAAC;YACzC,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YACrC,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC,YAAY,CAAC;YAClC,OAAO,MAAM,CAAC;QAChB,CAAC;QAED;YACE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC9B,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ratio-mcp/docs-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"files": ["dist"],
|
|
7
|
+
"bin": {
|
|
8
|
+
"ratio-docs-server": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc && rm -rf dist/schemas && cp -r src/schemas dist/schemas",
|
|
12
|
+
"dev": "node --loader ts-node/esm src/index.ts",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"prepublishOnly": "pnpm build"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
19
|
+
"@ratio-mcp/shared": "workspace:^",
|
|
20
|
+
"zod": "^3.23.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^20.0.0",
|
|
24
|
+
"typescript": "^5.4.0"
|
|
25
|
+
}
|
|
26
|
+
}
|