swagger-digest 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -2
- package/README.md +135 -1
- package/dist/chunk-2NORV6KM.js +143 -0
- package/dist/{chunk-UZQM2SHL.js → chunk-U7OLLL6J.js} +1313 -517
- package/dist/cli.js +90 -8
- package/dist/index.d.ts +107 -5
- package/dist/index.js +9 -1
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +16 -0
- package/package.json +14 -13
package/dist/cli.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
VERSION,
|
|
3
4
|
defaultFilename,
|
|
4
5
|
defaultOutputDirectory,
|
|
5
6
|
estimateTokens,
|
|
6
7
|
fetchOpenApiSpec,
|
|
8
|
+
mergeHeaders,
|
|
9
|
+
parseHeaderArgument,
|
|
10
|
+
parseHeaderPairs,
|
|
7
11
|
transformOpenApiToMarkdown,
|
|
8
12
|
writeDigest
|
|
9
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U7OLLL6J.js";
|
|
10
14
|
|
|
11
15
|
// src/cli.ts
|
|
12
16
|
import { input } from "@inquirer/prompts";
|
|
@@ -25,11 +29,65 @@ function validateUrl(value) {
|
|
|
25
29
|
function isInteractive() {
|
|
26
30
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
27
31
|
}
|
|
32
|
+
function parseMaxBytes(value) {
|
|
33
|
+
if (value === void 0) return void 0;
|
|
34
|
+
const parsed = Number(value);
|
|
35
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
36
|
+
throw new Error(`Invalid --max-bytes value: ${value}. Use a positive integer number of bytes.`);
|
|
37
|
+
}
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
function parseMaxTokens(value) {
|
|
41
|
+
if (value === void 0) return void 0;
|
|
42
|
+
const parsed = Number(value);
|
|
43
|
+
if (!Number.isFinite(parsed) || parsed <= 0 || !Number.isInteger(parsed)) {
|
|
44
|
+
throw new Error(`Invalid --max-tokens value: ${value}. Use a positive integer number of tokens.`);
|
|
45
|
+
}
|
|
46
|
+
return parsed;
|
|
47
|
+
}
|
|
48
|
+
function collectOption(value, previous) {
|
|
49
|
+
return [...previous ?? [], value];
|
|
50
|
+
}
|
|
51
|
+
function buildRequestHeaders(options) {
|
|
52
|
+
const fromEnv = process.env.SWAGGER_DIGEST_HEADER ? parseHeaderPairs(process.env.SWAGGER_DIGEST_HEADER) : {};
|
|
53
|
+
const fromFlags = (options.headers ?? []).map(parseHeaderArgument);
|
|
54
|
+
const cookieHeader = options.cookie !== void 0 ? parseHeaderArgument(`Cookie: ${options.cookie}`) : {};
|
|
55
|
+
return mergeHeaders(fromEnv, ...fromFlags, cookieHeader);
|
|
56
|
+
}
|
|
28
57
|
async function main() {
|
|
29
58
|
const program = new Command();
|
|
30
|
-
program.name("swagger-digest").description("Convert a Swagger UI page or OpenAPI URL into compact, AI-friendly Markdown.").version(
|
|
59
|
+
program.name("swagger-digest").description("Convert a Swagger UI page or OpenAPI URL into compact, AI-friendly Markdown.").version(VERSION).option("-u, --url <url>", "Swagger UI page URL or direct OpenAPI spec URL").option("-d, --out-dir <directory>", "Directory where the Markdown digest will be saved").option("-f, --filename <filename>", "Output filename (defaults to <api-title>-digest.md)").option("--no-browser", "Disable the optional Playwright headless-browser fallback").option("--max-bytes <bytes>", "Maximum response size in bytes (default 10000000 = 10 MB)", "10000000").option(
|
|
60
|
+
'-H, --header <"Name: value">',
|
|
61
|
+
"Custom request header, repeatable. Sent only to the URL you supplied.",
|
|
62
|
+
collectOption,
|
|
63
|
+
[]
|
|
64
|
+
).option("--cookie <string>", "Convenience for a Cookie request header (same-origin scoping applies)").option("--include-tag <tag>", "Keep only operations with this tag, repeatable", collectOption, []).option("--exclude-tag <tag>", "Drop operations with this tag, repeatable", collectOption, []).option("--path-prefix <prefix>", "Keep only operations whose path starts with this prefix").option("--max-tokens <n>", "Trim the digest until the approximate token estimate fits this budget").option("--spec <url>", "Explicit OpenAPI spec URL; overrides discovery from the Swagger UI page").option("--stdout", "Print the digest to standard output instead of writing a file").addHelpText(
|
|
31
65
|
"after",
|
|
32
|
-
|
|
66
|
+
[
|
|
67
|
+
"",
|
|
68
|
+
"Examples:",
|
|
69
|
+
" npx swagger-digest",
|
|
70
|
+
" npx swagger-digest --url https://petstore.swagger.io/ --out-dir ./docs",
|
|
71
|
+
" npx swagger-digest -u https://example.com/openapi.yaml -f payments-api.md",
|
|
72
|
+
' npx swagger-digest -u https://api.example.com/swagger-ui -H "Authorization: Bearer <token>"',
|
|
73
|
+
"",
|
|
74
|
+
"Authentication:",
|
|
75
|
+
" -H/--header and --cookie values are sent ONLY to the origin of --url.",
|
|
76
|
+
' You can also set SWAGGER_DIGEST_HEADER with newline-separated "Name: value" pairs;',
|
|
77
|
+
" -H flags override it on conflicts. Avoid passing secrets on the command line if",
|
|
78
|
+
" your shell saves history \u2014 prefer the environment variable.",
|
|
79
|
+
"",
|
|
80
|
+
"Filtering and token budget:",
|
|
81
|
+
" --include-tag/--exclude-tag/--path-prefix remove operations (and the data",
|
|
82
|
+
" models only they referenced) before rendering.",
|
|
83
|
+
" --max-tokens trims the digest in this order until the estimate fits:",
|
|
84
|
+
" 1. drop declared example payloads \u2192 2. shorten descriptions \u2192",
|
|
85
|
+
" 3. collapse parameter/response detail per tag (lowest-priority tag first:",
|
|
86
|
+
" the tag that appears last in the document is collapsed first) \u2192",
|
|
87
|
+
' 4. keep only the Quick index entries. A "Trimmed" note records what was',
|
|
88
|
+
" removed. The estimator is a heuristic, NOT tokenizer-accurate \u2014 treat the",
|
|
89
|
+
" budget as a guide, not a guarantee."
|
|
90
|
+
].join("\n")
|
|
33
91
|
);
|
|
34
92
|
program.parse(process.argv);
|
|
35
93
|
const options = program.opts();
|
|
@@ -42,22 +100,45 @@ async function main() {
|
|
|
42
100
|
});
|
|
43
101
|
const validUrl = validateUrl(url);
|
|
44
102
|
if (validUrl !== true) throw new Error(validUrl);
|
|
45
|
-
|
|
103
|
+
if (options.stdout && (options.outDir !== void 0 || options.filename !== void 0)) {
|
|
104
|
+
throw new Error(
|
|
105
|
+
"--stdout cannot be combined with --out-dir or --filename: it prints the digest to standard output instead of writing a file. Drop --stdout, or remove --out-dir/--filename."
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
const outputDirectory = options.outDir ?? (isInteractive() && !options.stdout ? await input({
|
|
46
109
|
message: "Destination directory",
|
|
47
110
|
default: defaultOutputDirectory(),
|
|
48
111
|
validate: (value) => value.trim() ? true : "Enter a destination directory."
|
|
49
112
|
}) : defaultOutputDirectory());
|
|
113
|
+
const maxBytes = parseMaxBytes(options.maxBytes);
|
|
114
|
+
const requestHeaders = buildRequestHeaders(options);
|
|
50
115
|
const spinner = ora({ text: "Fetching and parsing OpenAPI definition\u2026", color: "cyan" }).start();
|
|
51
116
|
let result;
|
|
52
117
|
try {
|
|
53
|
-
result = await fetchOpenApiSpec(url, {
|
|
118
|
+
result = await fetchOpenApiSpec(url, {
|
|
119
|
+
useBrowserFallback: options.browser !== false,
|
|
120
|
+
maxBytes,
|
|
121
|
+
headers: requestHeaders,
|
|
122
|
+
specUrl: options.spec,
|
|
123
|
+
warn: (message) => console.error(chalk.yellow(`Warning: ${message}`))
|
|
124
|
+
});
|
|
54
125
|
} catch (error) {
|
|
55
126
|
spinner.fail("Could not extract an OpenAPI definition");
|
|
56
127
|
throw error;
|
|
57
128
|
}
|
|
58
129
|
const title = typeof result.spec.info?.title === "string" ? result.spec.info.title : "API";
|
|
59
|
-
const markdown = transformOpenApiToMarkdown(result.spec, result.sourceUrl
|
|
130
|
+
const markdown = transformOpenApiToMarkdown(result.spec, result.sourceUrl, {
|
|
131
|
+
includeTags: options.includeTag,
|
|
132
|
+
excludeTags: options.excludeTag,
|
|
133
|
+
pathPrefix: options.pathPrefix,
|
|
134
|
+
maxTokens: parseMaxTokens(options.maxTokens),
|
|
135
|
+
onWarning: (message) => console.error(chalk.yellow(`Warning: ${message}`))
|
|
136
|
+
});
|
|
60
137
|
spinner.succeed(`Parsed ${title} (${result.retrievalMethod})`);
|
|
138
|
+
if (options.stdout) {
|
|
139
|
+
process.stdout.write(markdown);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
61
142
|
const filename = options.filename ?? (isInteractive() ? await input({
|
|
62
143
|
message: "Output filename",
|
|
63
144
|
default: defaultFilename(title),
|
|
@@ -71,7 +152,8 @@ async function main() {
|
|
|
71
152
|
const endpointCount = Object.values(result.spec.paths ?? {}).reduce((count, pathItem) => {
|
|
72
153
|
if (!pathItem || typeof pathItem !== "object") return count;
|
|
73
154
|
const methods = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
74
|
-
|
|
155
|
+
const operations = pathItem;
|
|
156
|
+
return count + methods.filter((method) => operations[method] && typeof operations[method] === "object").length;
|
|
75
157
|
}, 0);
|
|
76
158
|
const modelCount = Object.keys(result.spec.components?.schemas ?? result.spec.definitions ?? {}).length;
|
|
77
159
|
console.log("");
|
|
@@ -82,7 +164,7 @@ async function main() {
|
|
|
82
164
|
}
|
|
83
165
|
console.log(` ${chalk.dim("\u2022")} Characters: ${chalk.dim(report.characters.toLocaleString())}`);
|
|
84
166
|
console.log("");
|
|
85
|
-
console.log(chalk.bold("Estimated token usage (
|
|
167
|
+
console.log(chalk.bold("Estimated token usage (approximate):"));
|
|
86
168
|
for (const model of Object.values(report.models)) {
|
|
87
169
|
const windowLabel = model.contextWindow >= 1e6 ? `${model.contextWindow / 1e6}M` : `${model.contextWindow / 1e3}k`;
|
|
88
170
|
const paddedName = `${model.name}:`.padEnd(30, " ");
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,33 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
|
|
1
4
|
type JsonObject = Record<string, any>;
|
|
2
5
|
interface FetchOptions {
|
|
3
6
|
timeoutMs?: number;
|
|
4
7
|
useBrowserFallback?: boolean;
|
|
8
|
+
/** Maximum response body size in bytes (default 10 MB). */
|
|
9
|
+
maxBytes?: number;
|
|
10
|
+
/** Maximum number of redirects to follow (default 5). */
|
|
11
|
+
maxRedirects?: number;
|
|
12
|
+
/** Opt-in: reject hostnames resolving to private/loopback/metadata addresses. */
|
|
13
|
+
blockPrivateNetworks?: boolean;
|
|
14
|
+
/** Timeout for fallback-path probes (default 5000ms; main requests use timeoutMs). */
|
|
15
|
+
probeTimeoutMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Custom request headers (e.g. Authorization or Cookie). These are sent ONLY
|
|
18
|
+
* to the origin of the URL passed to fetchOpenApiSpec; cross-origin requests
|
|
19
|
+
* (including cross-origin redirects and third-party browser requests) never
|
|
20
|
+
* receive them.
|
|
21
|
+
*/
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
/** Receives non-fatal notices, e.g. headers withheld on a cross-origin fetch. */
|
|
24
|
+
warn?: (message: string) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Explicit spec URL that overrides discovery entirely: it is fetched first
|
|
27
|
+
* (with the same header scoping as the main URL) and the page is never
|
|
28
|
+
* consulted when it parses successfully.
|
|
29
|
+
*/
|
|
30
|
+
specUrl?: string;
|
|
5
31
|
}
|
|
6
32
|
interface FetchResult {
|
|
7
33
|
spec: JsonObject;
|
|
@@ -15,9 +41,84 @@ declare function parseSpecText(text: string, source?: string): JsonObject;
|
|
|
15
41
|
/** Resolve a Swagger UI page or a direct OpenAPI JSON/YAML URL into a parsed spec. */
|
|
16
42
|
declare function fetchOpenApiSpec(input: string, options?: FetchOptions): Promise<FetchResult>;
|
|
17
43
|
|
|
44
|
+
/** Arguments of the `swagger_digest` MCP tool (mirrors the zod schema in server.ts). */
|
|
45
|
+
interface McpDigestArgs {
|
|
46
|
+
/** Swagger UI page URL or direct OpenAPI spec URL. */
|
|
47
|
+
url: string;
|
|
48
|
+
/** Explicit spec URL; overrides discovery from the Swagger UI page. */
|
|
49
|
+
spec_url?: string;
|
|
50
|
+
/** Request headers (e.g. Authorization). Sent only to the origin of `url`. */
|
|
51
|
+
headers?: Record<string, string>;
|
|
52
|
+
/** Keep only operations carrying at least one of these tags. */
|
|
53
|
+
include_tags?: string[];
|
|
54
|
+
/** Drop operations carrying any of these tags. */
|
|
55
|
+
exclude_tags?: string[];
|
|
56
|
+
/** Keep only operations whose path starts with this prefix. */
|
|
57
|
+
path_prefix?: string;
|
|
58
|
+
/** Trim the digest until the approximate token estimate fits this budget. */
|
|
59
|
+
max_tokens?: number;
|
|
60
|
+
/** Save the digest to a file instead of returning it inline. */
|
|
61
|
+
write_to_file?: {
|
|
62
|
+
directory: string;
|
|
63
|
+
filename: string;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Server-wide behavior switches. Tests pass these explicitly; the stdio entry
|
|
68
|
+
* point derives them from the environment.
|
|
69
|
+
*/
|
|
70
|
+
interface DigestServerOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Reject URLs resolving to loopback/private/metadata addresses. Defaults to
|
|
73
|
+
* true: an MCP client supplies URLs on the model's behalf, which is exactly
|
|
74
|
+
* the "server that accepts user-supplied URLs" case from the security notes.
|
|
75
|
+
* Users can opt out per deployment with SWAGGER_DIGEST_ALLOW_PRIVATE=1.
|
|
76
|
+
*/
|
|
77
|
+
blockPrivateNetworks?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Builds the request headers for a digest call: SWAGGER_DIGEST_HEADER
|
|
81
|
+
* environment entries first, then tool-call arguments (arguments win on
|
|
82
|
+
* conflicting names — same precedence as -H flags over the environment in the
|
|
83
|
+
* CLI). Header validation and origin scoping happen in headers.ts / fetcher.ts.
|
|
84
|
+
*/
|
|
85
|
+
declare function buildRequestHeaders(args: Pick<McpDigestArgs, 'headers'>): Record<string, string>;
|
|
86
|
+
/**
|
|
87
|
+
* Runs one digest request and renders it as an MCP tool result. Expected
|
|
88
|
+
* failures (unreachable URLs, unparsable specs, invalid header arguments)
|
|
89
|
+
* become `isError` results carrying the message; unexpected errors propagate
|
|
90
|
+
* to the SDK, which converts them into protocol-level tool errors.
|
|
91
|
+
*/
|
|
92
|
+
declare function runSwaggerDigest(args: McpDigestArgs, options?: DigestServerOptions): Promise<CallToolResult>;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Builds the MCP server exposing the `swagger_digest` tool.
|
|
96
|
+
*
|
|
97
|
+
* The instance is transport-agnostic: `src/mcp/index.ts` connects it to a
|
|
98
|
+
* StdioServerTransport, while tests connect it to an InMemoryTransport pair.
|
|
99
|
+
* No I/O happens at module scope or during construction.
|
|
100
|
+
*/
|
|
101
|
+
declare function createMcpServer(options?: DigestServerOptions): McpServer;
|
|
102
|
+
|
|
18
103
|
declare function toTypeScriptIdentifier(value: string): string;
|
|
104
|
+
|
|
105
|
+
interface TransformOptions {
|
|
106
|
+
/** Keep only operations carrying at least one of these tags. Repeatable. */
|
|
107
|
+
includeTags?: string[];
|
|
108
|
+
/** Drop operations carrying any of these tags. Repeatable. */
|
|
109
|
+
excludeTags?: string[];
|
|
110
|
+
/** Keep only operations whose path starts with this prefix. */
|
|
111
|
+
pathPrefix?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Trim the digest until the (approximate, heuristic) token estimate fits this
|
|
114
|
+
* budget. The estimator is not tokenizer-accurate; treat the budget as a guide.
|
|
115
|
+
*/
|
|
116
|
+
maxTokens?: number;
|
|
117
|
+
/** Receives non-fatal notices, e.g. unknown tag names. */
|
|
118
|
+
onWarning?: (message: string) => void;
|
|
119
|
+
}
|
|
19
120
|
/** Convert an OpenAPI 2.0, 3.0, or 3.1 document to a compact Markdown digest. */
|
|
20
|
-
declare function transformOpenApiToMarkdown(spec: JsonObject, sourceUrl?: string): string;
|
|
121
|
+
declare function transformOpenApiToMarkdown(spec: JsonObject, sourceUrl?: string, options?: TransformOptions): string;
|
|
21
122
|
|
|
22
123
|
interface ModelTokenEstimate {
|
|
23
124
|
name: string;
|
|
@@ -36,8 +137,9 @@ interface DigestTokenReport {
|
|
|
36
137
|
};
|
|
37
138
|
}
|
|
38
139
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
140
|
+
* Produces ROUGH token-count estimates for Markdown/code. The numbers are a
|
|
141
|
+
* heuristic (word + symbol density with per-model multipliers), not accurate
|
|
142
|
+
* tokenizer counts — use them as an order-of-magnitude guide only.
|
|
41
143
|
*/
|
|
42
144
|
declare function estimateTokens(text: string): DigestTokenReport;
|
|
43
145
|
|
|
@@ -51,5 +153,5 @@ declare function writeDigest(options: {
|
|
|
51
153
|
filename: string;
|
|
52
154
|
}): Promise<string>;
|
|
53
155
|
|
|
54
|
-
export { defaultFilename, defaultOutputDirectory, estimateTokens, fetchOpenApiSpec, isOpenApiSpec, normalizeFilename, parseSpecText, resolveOutputDirectory, toTypeScriptIdentifier, transformOpenApiToMarkdown, writeDigest };
|
|
55
|
-
export type { DigestTokenReport, FetchOptions, FetchResult, JsonObject, ModelTokenEstimate };
|
|
156
|
+
export { buildRequestHeaders, createMcpServer, defaultFilename, defaultOutputDirectory, estimateTokens, fetchOpenApiSpec, isOpenApiSpec, normalizeFilename, parseSpecText, resolveOutputDirectory, runSwaggerDigest, toTypeScriptIdentifier, transformOpenApiToMarkdown, writeDigest };
|
|
157
|
+
export type { DigestServerOptions, DigestTokenReport, FetchOptions, FetchResult, JsonObject, McpDigestArgs, ModelTokenEstimate, TransformOptions };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildRequestHeaders,
|
|
3
|
+
createMcpServer,
|
|
4
|
+
runSwaggerDigest
|
|
5
|
+
} from "./chunk-2NORV6KM.js";
|
|
1
6
|
import {
|
|
2
7
|
defaultFilename,
|
|
3
8
|
defaultOutputDirectory,
|
|
@@ -10,8 +15,10 @@ import {
|
|
|
10
15
|
toTypeScriptIdentifier,
|
|
11
16
|
transformOpenApiToMarkdown,
|
|
12
17
|
writeDigest
|
|
13
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-U7OLLL6J.js";
|
|
14
19
|
export {
|
|
20
|
+
buildRequestHeaders,
|
|
21
|
+
createMcpServer,
|
|
15
22
|
defaultFilename,
|
|
16
23
|
defaultOutputDirectory,
|
|
17
24
|
estimateTokens,
|
|
@@ -20,6 +27,7 @@ export {
|
|
|
20
27
|
normalizeFilename,
|
|
21
28
|
parseSpecText,
|
|
22
29
|
resolveOutputDirectory,
|
|
30
|
+
runSwaggerDigest,
|
|
23
31
|
toTypeScriptIdentifier,
|
|
24
32
|
transformOpenApiToMarkdown,
|
|
25
33
|
writeDigest
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
createMcpServer
|
|
4
|
+
} from "../chunk-2NORV6KM.js";
|
|
5
|
+
import "../chunk-U7OLLL6J.js";
|
|
6
|
+
|
|
7
|
+
// src/mcp/index.ts
|
|
8
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
9
|
+
async function main() {
|
|
10
|
+
const server = createMcpServer();
|
|
11
|
+
await server.connect(new StdioServerTransport());
|
|
12
|
+
}
|
|
13
|
+
main().catch((error) => {
|
|
14
|
+
console.error(error instanceof Error ? error.stack ?? error.message : String(error));
|
|
15
|
+
process.exitCode = 1;
|
|
16
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swagger-digest",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Turn Swagger UI pages and OpenAPI specs into compact, AI-friendly Markdown API digests.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"swagger-digest": "dist/cli.js"
|
|
15
|
+
"swagger-digest": "./dist/cli.js",
|
|
16
|
+
"swagger-digest-mcp": "./dist/mcp/index.js"
|
|
16
17
|
},
|
|
17
18
|
"author": "VladLegkowski <VladLegkowski@users.noreply.github.com>",
|
|
18
19
|
"repository": {
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
"LICENSE"
|
|
31
32
|
],
|
|
32
33
|
"scripts": {
|
|
33
|
-
"build": "tsup src/index.ts src/cli.ts --format esm --dts --clean",
|
|
34
|
+
"build": "tsup src/index.ts src/cli.ts src/mcp/index.ts --format esm --dts --clean",
|
|
34
35
|
"dev": "tsx src/cli.ts",
|
|
35
36
|
"start": "node dist/cli.js",
|
|
36
37
|
"typecheck": "tsc --noEmit",
|
|
@@ -39,18 +40,20 @@
|
|
|
39
40
|
"lint": "eslint .",
|
|
40
41
|
"prepare": "husky",
|
|
41
42
|
"prepack": "npm run build",
|
|
42
|
-
"prepublishOnly": "npm
|
|
43
|
+
"prepublishOnly": "npm test"
|
|
43
44
|
},
|
|
44
45
|
"engines": {
|
|
45
|
-
"node": ">=20
|
|
46
|
+
"node": ">=20"
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
49
|
"@inquirer/prompts": "^7.3.2",
|
|
50
|
+
"@modelcontextprotocol/sdk": "^1.32.2",
|
|
49
51
|
"chalk": "^5.4.1",
|
|
50
52
|
"cheerio": "^1.0.0",
|
|
51
53
|
"commander": "^13.1.0",
|
|
52
54
|
"ora": "^8.2.0",
|
|
53
|
-
"yaml": "^2.7.0"
|
|
55
|
+
"yaml": "^2.7.0",
|
|
56
|
+
"zod": "^4.6.7"
|
|
54
57
|
},
|
|
55
58
|
"devDependencies": {
|
|
56
59
|
"@types/node": "^22.15.0",
|
|
@@ -73,14 +76,12 @@
|
|
|
73
76
|
}
|
|
74
77
|
},
|
|
75
78
|
"keywords": [
|
|
76
|
-
"swagger",
|
|
77
79
|
"openapi",
|
|
78
|
-
"
|
|
79
|
-
"ai",
|
|
80
|
-
"llm",
|
|
80
|
+
"swagger",
|
|
81
81
|
"markdown",
|
|
82
|
-
"
|
|
83
|
-
"ai-coding-agent"
|
|
82
|
+
"llm",
|
|
83
|
+
"ai-coding-agent",
|
|
84
|
+
"cli"
|
|
84
85
|
],
|
|
85
86
|
"license": "MIT"
|
|
86
87
|
}
|