@thupham/volley-mcp 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.
Files changed (61) hide show
  1. package/dist/collections.d.ts +50 -0
  2. package/dist/collections.js +125 -0
  3. package/dist/collections.js.map +1 -0
  4. package/dist/curl.d.ts +14 -0
  5. package/dist/curl.js +90 -0
  6. package/dist/curl.js.map +1 -0
  7. package/dist/format.d.ts +10 -0
  8. package/dist/format.js +70 -0
  9. package/dist/format.js.map +1 -0
  10. package/dist/importers.d.ts +75 -0
  11. package/dist/importers.js +164 -0
  12. package/dist/importers.js.map +1 -0
  13. package/dist/index.d.ts +2 -0
  14. package/dist/index.js +40 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/junit.d.ts +5 -0
  17. package/dist/junit.js +30 -0
  18. package/dist/junit.js.map +1 -0
  19. package/dist/native.d.ts +56 -0
  20. package/dist/native.js +44 -0
  21. package/dist/native.js.map +1 -0
  22. package/dist/session.d.ts +52 -0
  23. package/dist/session.js +135 -0
  24. package/dist/session.js.map +1 -0
  25. package/dist/tools/collections.d.ts +3 -0
  26. package/dist/tools/collections.js +50 -0
  27. package/dist/tools/collections.js.map +1 -0
  28. package/dist/tools/env.d.ts +3 -0
  29. package/dist/tools/env.js +33 -0
  30. package/dist/tools/env.js.map +1 -0
  31. package/dist/tools/graphql.d.ts +3 -0
  32. package/dist/tools/graphql.js +44 -0
  33. package/dist/tools/graphql.js.map +1 -0
  34. package/dist/tools/importCurl.d.ts +3 -0
  35. package/dist/tools/importCurl.js +36 -0
  36. package/dist/tools/importCurl.js.map +1 -0
  37. package/dist/tools/importers.d.ts +2 -0
  38. package/dist/tools/importers.js +62 -0
  39. package/dist/tools/importers.js.map +1 -0
  40. package/dist/tools/inspect.d.ts +3 -0
  41. package/dist/tools/inspect.js +102 -0
  42. package/dist/tools/inspect.js.map +1 -0
  43. package/dist/tools/ping.d.ts +6 -0
  44. package/dist/tools/ping.js +29 -0
  45. package/dist/tools/ping.js.map +1 -0
  46. package/dist/tools/policy.d.ts +3 -0
  47. package/dist/tools/policy.js +28 -0
  48. package/dist/tools/policy.js.map +1 -0
  49. package/dist/tools/request.d.ts +3 -0
  50. package/dist/tools/request.js +111 -0
  51. package/dist/tools/request.js.map +1 -0
  52. package/dist/tools/save.d.ts +3 -0
  53. package/dist/tools/save.js +67 -0
  54. package/dist/tools/save.js.map +1 -0
  55. package/dist/tools/stream.d.ts +3 -0
  56. package/dist/tools/stream.js +76 -0
  57. package/dist/tools/stream.js.map +1 -0
  58. package/dist/tools/ws.d.ts +3 -0
  59. package/dist/tools/ws.js +68 -0
  60. package/dist/tools/ws.js.map +1 -0
  61. package/package.json +38 -0
package/dist/index.js ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { Session } from "./session.js";
5
+ import { coreVersion } from "./native.js";
6
+ import { registerRequestTools } from "./tools/request.js";
7
+ import { registerStreamTools } from "./tools/stream.js";
8
+ import { registerInspectTool } from "./tools/inspect.js";
9
+ import { registerEnvTools } from "./tools/env.js";
10
+ import { registerCollectionTools } from "./tools/collections.js";
11
+ import { registerImportCurlTool } from "./tools/importCurl.js";
12
+ import { registerGraphqlTools } from "./tools/graphql.js";
13
+ import { registerWsTools } from "./tools/ws.js";
14
+ import { registerSaveTool } from "./tools/save.js";
15
+ import { registerPolicyTool } from "./tools/policy.js";
16
+ import { registerImporterTools } from "./tools/importers.js";
17
+ async function main() {
18
+ const server = new McpServer({ name: "volley", version: "1.0.1" });
19
+ const session = new Session();
20
+ registerRequestTools(server, session);
21
+ registerStreamTools(server, session);
22
+ registerInspectTool(server, session);
23
+ registerEnvTools(server, session);
24
+ registerCollectionTools(server, session);
25
+ registerImportCurlTool(server, session);
26
+ registerGraphqlTools(server, session);
27
+ registerWsTools(server, session);
28
+ registerSaveTool(server, session);
29
+ registerPolicyTool(server, session);
30
+ registerImporterTools(server);
31
+ // stdout is reserved for the MCP JSON-RPC stream; log to stderr only.
32
+ process.stderr.write(`volley starting (core v${coreVersion()})\n`);
33
+ const transport = new StdioServerTransport();
34
+ await server.connect(transport);
35
+ }
36
+ main().catch((err) => {
37
+ process.stderr.write(`fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
38
+ process.exit(1);
39
+ });
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,uBAAuB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,sBAAsB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,gBAAgB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAE9B,sEAAsE;IACtE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0BAA0B,WAAW,EAAE,KAAK,CAAC,CAAC;IAEnE,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Serialize a RunReport (from run_collection) into JUnit XML for CI consumption.
3
+ */
4
+ import type { RunReport } from "./collections.js";
5
+ export declare function toJUnitXml(report: RunReport): string;
package/dist/junit.js ADDED
@@ -0,0 +1,30 @@
1
+ function esc(s) {
2
+ return s
3
+ .replace(/&/g, "&")
4
+ .replace(/</g, "&lt;")
5
+ .replace(/>/g, "&gt;")
6
+ .replace(/"/g, "&quot;")
7
+ .replace(/'/g, "&apos;");
8
+ }
9
+ export function toJUnitXml(report) {
10
+ const cases = report.steps
11
+ .map((s) => {
12
+ const name = esc(s.id);
13
+ const time = ""; // timing not tracked per step yet
14
+ if (s.skipped) {
15
+ return ` <testcase name="${name}" time="${time}"><skipped/></testcase>`;
16
+ }
17
+ if (s.ok) {
18
+ return ` <testcase name="${name}" time="${time}"/>`;
19
+ }
20
+ const failure = s.failures?.map((f) => esc(f)).join("; ") ?? (s.error ? esc(s.error) : "failed");
21
+ return ` <testcase name="${name}" time="${time}"><failure message="${failure}">${failure}</failure></testcase>`;
22
+ })
23
+ .join("\n");
24
+ return `<?xml version="1.0" encoding="UTF-8"?>
25
+ <testsuite name="${esc(report.name)}" tests="${report.steps.length}" failures="${report.failed}" skipped="${report.skipped}">
26
+ ${cases}
27
+ </testsuite>
28
+ `;
29
+ }
30
+ //# sourceMappingURL=junit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"junit.js","sourceRoot":"","sources":["../src/junit.ts"],"names":[],"mappings":"AAKA,SAAS,GAAG,CAAC,CAAS;IACpB,OAAO,CAAC;SACL,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,EAAE,CAAC,CAAC,kCAAkC;QACnD,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YACd,OAAO,uBAAuB,IAAI,WAAW,IAAI,yBAAyB,CAAC;QAC7E,CAAC;QACD,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;YACT,OAAO,uBAAuB,IAAI,WAAW,IAAI,KAAK,CAAC;QACzD,CAAC;QACD,MAAM,OAAO,GAAG,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QACjG,OAAO,uBAAuB,IAAI,WAAW,IAAI,uBAAuB,OAAO,KAAK,OAAO,uBAAuB,CAAC;IACrH,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;mBACU,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,KAAK,CAAC,MAAM,eAAe,MAAM,CAAC,MAAM,cAAc,MAAM,CAAC,OAAO;EACxH,KAAK;;CAEN,CAAC;AACF,CAAC"}
@@ -0,0 +1,56 @@
1
+ export declare function coreVersion(): string;
2
+ /** Standard result document returned by the execution functions. */
3
+ export interface ExecResult {
4
+ ok: boolean;
5
+ error: string | null;
6
+ status?: number | null;
7
+ statusText?: string;
8
+ timeMs?: number;
9
+ headers?: Record<string, string>;
10
+ bodyJson?: unknown;
11
+ bodyText?: string | null;
12
+ bodyBytes?: number;
13
+ bodyShape?: unknown;
14
+ bodyPreview?: unknown;
15
+ assertions?: AssertionReport;
16
+ extracted?: Record<string, unknown>;
17
+ graphqlErrors?: unknown;
18
+ connected?: boolean;
19
+ frameCount?: number;
20
+ frames?: unknown[];
21
+ framesPreview?: unknown;
22
+ eventCount?: number;
23
+ events?: unknown[];
24
+ eventsPreview?: unknown;
25
+ note?: string | null;
26
+ schema?: unknown;
27
+ handle?: string;
28
+ count?: number;
29
+ remaining?: number;
30
+ closed?: boolean;
31
+ }
32
+ export interface AssertionReport {
33
+ passed: number;
34
+ failed: number;
35
+ skipped: number;
36
+ results: {
37
+ ok: boolean;
38
+ skipped?: boolean;
39
+ desc: string;
40
+ detail?: string;
41
+ }[];
42
+ }
43
+ export declare function httpRequest(spec: unknown): Promise<ExecResult>;
44
+ export declare function graphqlRequest(spec: unknown): Promise<ExecResult>;
45
+ export declare function graphqlIntrospect(spec: unknown): Promise<ExecResult>;
46
+ export declare function wsSession(spec: unknown): Promise<ExecResult>;
47
+ export declare function wsOpen(spec: unknown): Promise<ExecResult>;
48
+ export declare function wsSend(handle: string, message: unknown): ExecResult;
49
+ export declare function wsRecv(spec: unknown): Promise<ExecResult>;
50
+ export declare function wsClose(handle: string): ExecResult;
51
+ export declare function sseSession(spec: unknown): Promise<ExecResult>;
52
+ export declare function jsonQuery(document: unknown, path: string): {
53
+ found: boolean;
54
+ value: unknown;
55
+ error?: string;
56
+ };
package/dist/native.js ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Typed wrapper around the Rust core native addon (`@thupham/volley-core`).
3
+ *
4
+ * The addon is CommonJS (generated by napi-rs), so we load it via `createRequire`
5
+ * from this ES module. The FFI contract is JSON string in / JSON string out; we parse
6
+ * results here so the rest of the server works with plain objects.
7
+ */
8
+ import { createRequire } from "node:module";
9
+ const require = createRequire(import.meta.url);
10
+ const native = require("@thupham/volley-core");
11
+ export function coreVersion() {
12
+ return native.version();
13
+ }
14
+ export async function httpRequest(spec) {
15
+ return JSON.parse(await native.httpRequest(JSON.stringify(spec)));
16
+ }
17
+ export async function graphqlRequest(spec) {
18
+ return JSON.parse(await native.graphqlRequest(JSON.stringify(spec)));
19
+ }
20
+ export async function graphqlIntrospect(spec) {
21
+ return JSON.parse(await native.graphqlIntrospect(JSON.stringify(spec)));
22
+ }
23
+ export async function wsSession(spec) {
24
+ return JSON.parse(await native.wsSession(JSON.stringify(spec)));
25
+ }
26
+ export async function wsOpen(spec) {
27
+ return JSON.parse(await native.wsOpen(JSON.stringify(spec)));
28
+ }
29
+ export function wsSend(handle, message) {
30
+ return JSON.parse(native.wsSend(handle, JSON.stringify(message)));
31
+ }
32
+ export async function wsRecv(spec) {
33
+ return JSON.parse(await native.wsRecv(JSON.stringify(spec)));
34
+ }
35
+ export function wsClose(handle) {
36
+ return JSON.parse(native.wsClose(handle));
37
+ }
38
+ export async function sseSession(spec) {
39
+ return JSON.parse(await native.sseSession(JSON.stringify(spec)));
40
+ }
41
+ export function jsonQuery(document, path) {
42
+ return JSON.parse(native.jsonQuery(JSON.stringify(document), path));
43
+ }
44
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../src/native.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAgB/C,MAAM,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAe,CAAC;AAE7D,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,CAAC,OAAO,EAAE,CAAC;AAC1B,CAAC;AA0CD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAa;IAC7C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AAClF,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAAa;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AACrF,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAa;IACnD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AACxF,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAa;IAC3C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AAChF,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAa;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AAC7E,CAAC;AACD,MAAM,UAAU,MAAM,CAAC,MAAc,EAAE,OAAgB;IACrD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAe,CAAC;AAClF,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAa;IACxC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AAC7E,CAAC;AACD,MAAM,UAAU,OAAO,CAAC,MAAc;IACpC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAe,CAAC;AAC1D,CAAC;AACD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAa;IAC5C,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAe,CAAC;AACjF,CAAC;AACD,MAAM,UAAU,SAAS,CAAC,QAAiB,EAAE,IAAY;IACvD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AACtE,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Per-process session state: environments, extracted (chained) variables, and the
3
+ * response store used by `inspect_response`. Also owns secret redaction.
4
+ */
5
+ import type { ExecResult } from "./native.js";
6
+ export type Verbosity = "summary" | "headers" | "full";
7
+ export interface Policy {
8
+ allow: string[];
9
+ deny: string[];
10
+ dryRun: boolean;
11
+ }
12
+ export declare class Session {
13
+ private envs;
14
+ private activeEnv;
15
+ private extracted;
16
+ private store;
17
+ private secretValues;
18
+ private counter;
19
+ private lastRequest;
20
+ policy: Policy;
21
+ setEnv(name: string, vars: Record<string, unknown>): void;
22
+ listEnvs(): string[];
23
+ /** Env variables (masked) for display. */
24
+ describeEnv(name?: string): Record<string, unknown>;
25
+ /** Merge env values + extracted vars into the map the Rust templating consumes. */
26
+ mergedVars(envName?: string): Record<string, unknown>;
27
+ applyExtracted(map: Record<string, unknown> | undefined): void;
28
+ /**
29
+ * Validate a URL against the active policy. Returns an error string if the URL is denied,
30
+ * or a synthetic dry-run result object when dryRun is enabled. Returns null when the request
31
+ * should proceed normally.
32
+ */
33
+ checkPolicy(url: string): {
34
+ blocked: true;
35
+ error: string;
36
+ } | {
37
+ dryRun: true;
38
+ result: import("./native.js").ExecResult;
39
+ } | null;
40
+ private trackSecret;
41
+ /** Redact any known secret substrings from a payload. */
42
+ redact<T>(payload: T): T;
43
+ storeResponse(result: ExecResult): string;
44
+ getStored(handle: string): ExecResult | undefined;
45
+ recordRequest(type: string, request: Record<string, unknown>, assert?: unknown[], extract?: Record<string, string>): void;
46
+ consumeLastRequest(): {
47
+ type: string;
48
+ request: Record<string, unknown>;
49
+ assert?: unknown[];
50
+ extract?: Record<string, string>;
51
+ } | undefined;
52
+ }
@@ -0,0 +1,135 @@
1
+ export class Session {
2
+ envs = new Map();
3
+ activeEnv;
4
+ extracted = {};
5
+ store = new Map();
6
+ secretValues = new Set();
7
+ counter = 0;
8
+ lastRequest;
9
+ policy = { allow: [], deny: [], dryRun: false };
10
+ setEnv(name, vars) {
11
+ const normalized = {};
12
+ for (const [k, v] of Object.entries(vars)) {
13
+ if (v && typeof v === "object" && "value" in v) {
14
+ const ev = v;
15
+ normalized[k] = { value: ev.value, secret: ev.secret };
16
+ if (ev.secret)
17
+ this.trackSecret(ev.value);
18
+ }
19
+ else {
20
+ normalized[k] = { value: v };
21
+ }
22
+ }
23
+ this.envs.set(name, normalized);
24
+ this.activeEnv = name;
25
+ }
26
+ listEnvs() {
27
+ return [...this.envs.keys()];
28
+ }
29
+ /** Env variables (masked) for display. */
30
+ describeEnv(name) {
31
+ const env = this.envs.get(name ?? this.activeEnv ?? "");
32
+ if (!env)
33
+ return {};
34
+ const out = {};
35
+ for (const [k, v] of Object.entries(env))
36
+ out[k] = v.secret ? "***" : v.value;
37
+ return out;
38
+ }
39
+ /** Merge env values + extracted vars into the map the Rust templating consumes. */
40
+ mergedVars(envName) {
41
+ const merged = {};
42
+ const env = this.envs.get(envName ?? this.activeEnv ?? "");
43
+ if (env)
44
+ for (const [k, v] of Object.entries(env))
45
+ merged[k] = v.value;
46
+ Object.assign(merged, this.extracted);
47
+ // Expose env under `env.NAME` too (collections reference {{env.X}}).
48
+ merged.env = env
49
+ ? Object.fromEntries(Object.entries(env).map(([k, v]) => [k, v.value]))
50
+ : {};
51
+ return merged;
52
+ }
53
+ applyExtracted(map) {
54
+ if (map)
55
+ Object.assign(this.extracted, map);
56
+ }
57
+ /**
58
+ * Validate a URL against the active policy. Returns an error string if the URL is denied,
59
+ * or a synthetic dry-run result object when dryRun is enabled. Returns null when the request
60
+ * should proceed normally.
61
+ */
62
+ checkPolicy(url) {
63
+ let host = "";
64
+ try {
65
+ host = new URL(url).hostname;
66
+ }
67
+ catch {
68
+ host = url;
69
+ }
70
+ const denied = this.policy.deny.some((p) => matchHost(host, p));
71
+ if (denied)
72
+ return { blocked: true, error: `host '${host}' is denied by policy` };
73
+ const allowed = this.policy.allow.length === 0 || this.policy.allow.some((p) => matchHost(host, p));
74
+ if (!allowed)
75
+ return { blocked: true, error: `host '${host}' is not in the allow-list` };
76
+ if (this.policy.dryRun) {
77
+ return {
78
+ dryRun: true,
79
+ result: {
80
+ ok: true,
81
+ error: null,
82
+ status: null,
83
+ statusText: "DRY RUN",
84
+ note: "dry-run: request not sent",
85
+ },
86
+ };
87
+ }
88
+ return null;
89
+ }
90
+ trackSecret(value) {
91
+ if (typeof value === "string" && value.length >= 3)
92
+ this.secretValues.add(value);
93
+ }
94
+ /** Redact any known secret substrings from a payload. */
95
+ redact(payload) {
96
+ if (this.secretValues.size === 0)
97
+ return payload;
98
+ let text = JSON.stringify(payload);
99
+ for (const s of this.secretValues) {
100
+ text = text.split(s).join("***");
101
+ }
102
+ return JSON.parse(text);
103
+ }
104
+ storeResponse(result) {
105
+ const handle = `resp_${(++this.counter).toString(36)}`;
106
+ this.store.set(handle, result);
107
+ // Bound the store so long sessions don't grow unbounded.
108
+ if (this.store.size > 50) {
109
+ const oldest = this.store.keys().next().value;
110
+ if (oldest)
111
+ this.store.delete(oldest);
112
+ }
113
+ return handle;
114
+ }
115
+ getStored(handle) {
116
+ return this.store.get(handle);
117
+ }
118
+ recordRequest(type, request, assert, extract) {
119
+ this.lastRequest = { type, request, assert, extract };
120
+ }
121
+ consumeLastRequest() {
122
+ return this.lastRequest;
123
+ }
124
+ }
125
+ /** Glob-style host match: `*` matches any, `*.example.com` matches subdomains. */
126
+ function matchHost(host, pattern) {
127
+ if (pattern === "*")
128
+ return true;
129
+ if (pattern.startsWith("*.")) {
130
+ const suffix = pattern.slice(1); // ".example.com"
131
+ return host.endsWith(suffix) || host === suffix.slice(1);
132
+ }
133
+ return host === pattern;
134
+ }
135
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { Session } from "../session.js";
3
+ export declare function registerCollectionTools(server: McpServer, session: Session): void;
@@ -0,0 +1,50 @@
1
+ import { z } from "zod";
2
+ import { writeFileSync } from "node:fs";
3
+ import { listCollectionFiles, loadCollection, runCollection } from "../collections.js";
4
+ import { toJUnitXml } from "../junit.js";
5
+ export function registerCollectionTools(server, session) {
6
+ server.registerTool("list_collections", {
7
+ title: "List collections",
8
+ description: "Find collection files (.yaml/.yml/.json) under a directory.",
9
+ inputSchema: {
10
+ dir: z.string().optional().describe("Directory to scan. Defaults to the current working directory."),
11
+ },
12
+ }, async ({ dir }) => {
13
+ const files = listCollectionFiles(dir ?? process.cwd());
14
+ const items = files.map((path) => {
15
+ try {
16
+ const col = loadCollection(path);
17
+ return { path, name: col.name, steps: col.steps?.length ?? 0 };
18
+ }
19
+ catch {
20
+ return { path, error: "failed to parse" };
21
+ }
22
+ });
23
+ return { content: [{ type: "text", text: JSON.stringify(items, null, 2) }] };
24
+ });
25
+ server.registerTool("run_collection", {
26
+ title: "Run a collection",
27
+ description: "Run declarative collection file. Threads extracted vars between steps. Optional JUnit XML export.",
28
+ inputSchema: {
29
+ path: z.string().describe("Path to the collection file."),
30
+ env: z.string().optional().describe("Environment to resolve variables from."),
31
+ only: z.array(z.string()).optional().describe("Only run steps with these ids."),
32
+ tags: z.array(z.string()).optional().describe("Only run steps having any of these tags."),
33
+ junitPath: z.string().optional().describe("Write a JUnit XML report to this path."),
34
+ },
35
+ }, async ({ path, env, only, tags, junitPath }) => {
36
+ try {
37
+ const report = await runCollection(session, path, { env, only, tags });
38
+ if (junitPath)
39
+ writeFileSync(junitPath, toJUnitXml(report), "utf8");
40
+ return { content: [{ type: "text", text: JSON.stringify(session.redact(report), null, 2) }] };
41
+ }
42
+ catch (e) {
43
+ return {
44
+ isError: true,
45
+ content: [{ type: "text", text: `run_collection failed: ${e instanceof Error ? e.message : String(e)}` }],
46
+ };
47
+ }
48
+ });
49
+ }
50
+ //# sourceMappingURL=collections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/tools/collections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { Session } from "../session.js";
3
+ export declare function registerEnvTools(server: McpServer, session: Session): void;
@@ -0,0 +1,33 @@
1
+ import { z } from "zod";
2
+ export function registerEnvTools(server, session) {
3
+ server.registerTool("set_env", {
4
+ title: "Set environment variables",
5
+ description: "Create/update named env. Values may be {value, secret:true}. Use via {{name}}.",
6
+ inputSchema: {
7
+ name: z.string().describe("Environment name, e.g. 'dev'."),
8
+ vars: z
9
+ .record(z.string(), z.any())
10
+ .describe("Map of variables. Use { value, secret: true } to mark secrets."),
11
+ },
12
+ }, async ({ name, vars }) => {
13
+ session.setEnv(name, vars);
14
+ return {
15
+ content: [
16
+ { type: "text", text: JSON.stringify({ env: name, vars: session.describeEnv(name) }, null, 2) },
17
+ ],
18
+ };
19
+ });
20
+ server.registerTool("list_envs", {
21
+ title: "List environments",
22
+ description: "List env names and (masked) variables of the active or specified one.",
23
+ inputSchema: { name: z.string().optional().describe("Show variables for this env.") },
24
+ }, async ({ name }) => ({
25
+ content: [
26
+ {
27
+ type: "text",
28
+ text: JSON.stringify({ envs: session.listEnvs(), vars: session.describeEnv(name) }, null, 2),
29
+ },
30
+ ],
31
+ }));
32
+ }
33
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/tools/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,OAAgB;IAClE,MAAM,CAAC,YAAY,CACjB,SAAS,EACT;QACE,KAAK,EAAE,2BAA2B;QAClC,WAAW,EAAE,gFAAgF;QAC7F,WAAW,EAAE;YACX,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC1D,IAAI,EAAE,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;iBAC3B,QAAQ,CAAC,gEAAgE,CAAC;SAC9E;KACF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;QACvB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAA+B,CAAC,CAAC;QACtD,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aACzG;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,WAAW,EACX;QACE,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EAAE,uEAAuE;QACpF,WAAW,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC,EAAE;KACtF,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACnB,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;aAC7F;SACF;KACF,CAAC,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { Session } from "../session.js";
3
+ export declare function registerGraphqlTools(server: McpServer, session: Session): void;
@@ -0,0 +1,44 @@
1
+ import { z } from "zod";
2
+ import { graphqlIntrospect } from "../native.js";
3
+ const authSchema = z
4
+ .object({
5
+ type: z.enum(["bearer", "basic", "apikey"]),
6
+ token: z.string().optional(),
7
+ username: z.string().optional(),
8
+ password: z.string().optional(),
9
+ key: z.string().optional(),
10
+ value: z.string().optional(),
11
+ in: z.enum(["header", "query"]).optional(),
12
+ })
13
+ .optional();
14
+ export function registerGraphqlTools(server, session) {
15
+ server.registerTool("graphql_introspect", {
16
+ title: "GraphQL introspection",
17
+ description: "Introspect GraphQL endpoint, return summarized schema with field signatures (args + return types) and input types.",
18
+ inputSchema: {
19
+ url: z.string().describe("GraphQL endpoint URL."),
20
+ headers: z.record(z.string(), z.any()).optional(),
21
+ auth: authSchema,
22
+ env: z.string().optional(),
23
+ timeoutMs: z.number().int().positive().optional(),
24
+ },
25
+ }, async (args) => {
26
+ const spec = { ...args, vars: session.mergedVars(args.env) };
27
+ const result = await graphqlIntrospect(spec);
28
+ const handle = session.storeResponse(result);
29
+ const out = result.error
30
+ ? { ok: false, error: result.error }
31
+ : {
32
+ ok: result.ok,
33
+ status: result.status,
34
+ schema: result.schema,
35
+ graphqlErrors: result.graphqlErrors,
36
+ responseHandle: handle,
37
+ hint: "Use inspect_response with this handle to drill into the raw introspection payload.",
38
+ };
39
+ return {
40
+ content: [{ type: "text", text: JSON.stringify(session.redact(out), null, 2) }],
41
+ };
42
+ });
43
+ }
44
+ //# sourceMappingURL=graphql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"graphql.js","sourceRoot":"","sources":["../../src/tools/graphql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC3C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC3C,CAAC;KACD,QAAQ,EAAE,CAAC;AAEd,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,OAAgB;IACtE,MAAM,CAAC,YAAY,CACjB,oBAAoB,EACpB;QACE,KAAK,EAAE,uBAAuB;QAC9B,WAAW,EAAE,oHAAoH;QACjI,WAAW,EAAE;YACX,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;YACjD,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE;YACjD,IAAI,EAAE,UAAU;YAChB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;SAClD;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK;YACtB,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE;YACpC,CAAC,CAAC;gBACE,EAAE,EAAE,MAAM,CAAC,EAAE;gBACb,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,aAAa,EAAE,MAAM,CAAC,aAAa;gBACnC,cAAc,EAAE,MAAM;gBACtB,IAAI,EAAE,oFAAoF;aAC3F,CAAC;QACN,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACzF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import type { Session } from "../session.js";
3
+ export declare function registerImportCurlTool(server: McpServer, session: Session): void;
@@ -0,0 +1,36 @@
1
+ import { z } from "zod";
2
+ import { parseCurl } from "../curl.js";
3
+ import { httpRequest } from "../native.js";
4
+ import { formatHttp } from "../format.js";
5
+ export function registerImportCurlTool(server, session) {
6
+ server.registerTool("import_curl", {
7
+ title: "Import a curl command",
8
+ description: "Parse curl into structured request. Optionally execute it.",
9
+ inputSchema: {
10
+ curl: z.string().describe("The full curl command, e.g. \"curl -X POST https://... -H '...' -d '...'\"."),
11
+ execute: z.boolean().optional().describe("If true, run the parsed request and return the result."),
12
+ verbosity: z.enum(["summary", "headers", "full"]).optional(),
13
+ },
14
+ }, async ({ curl, execute, verbosity }) => {
15
+ const parsed = parseCurl(curl);
16
+ if (!execute) {
17
+ return { content: [{ type: "text", text: JSON.stringify({ parsed }, null, 2) }] };
18
+ }
19
+ const policy = session.checkPolicy(parsed.url);
20
+ if (policy && "blocked" in policy) {
21
+ return { content: [{ type: "text", text: JSON.stringify({ ok: false, error: policy.error }, null, 2) }] };
22
+ }
23
+ if (policy && "dryRun" in policy) {
24
+ const handle = session.storeResponse(policy.result);
25
+ const formatted = formatHttp(policy.result, verbosity ?? "summary", handle);
26
+ return { content: [{ type: "text", text: JSON.stringify(session.redact({ parsed, result: formatted }), null, 2) }] };
27
+ }
28
+ const result = await httpRequest({ ...parsed, vars: session.mergedVars() });
29
+ const handle = session.storeResponse(result);
30
+ const formatted = formatHttp(result, verbosity ?? "summary", handle);
31
+ return {
32
+ content: [{ type: "text", text: JSON.stringify(session.redact({ parsed, result: formatted }), null, 2) }],
33
+ };
34
+ });
35
+ }
36
+ //# sourceMappingURL=importCurl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"importCurl.js","sourceRoot":"","sources":["../../src/tools/importCurl.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerImporterTools(server: McpServer): void;