teppi-check 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/npm/cli.js CHANGED
@@ -6955,7 +6955,8 @@ function toolsFrom(result) {
6955
6955
  {
6956
6956
  name,
6957
6957
  description: text(tool.description),
6958
- hasInputSchema: typeof tool.inputSchema === "object" && tool.inputSchema !== null
6958
+ inputSchema: tool.inputSchema ?? null,
6959
+ outputSchema: tool.outputSchema ?? null
6959
6960
  }
6960
6961
  ];
6961
6962
  });
@@ -6981,6 +6982,8 @@ async function turn(response, method) {
6981
6982
  };
6982
6983
  }
6983
6984
  var DEADLINE_MS = 45e3;
6985
+ var MAX_PAGES = 20;
6986
+ var MAX_TOOLS = 2e3;
6984
6987
  async function probeMcp(url, options = {}) {
6985
6988
  const clockFor = options.now ?? Date.now;
6986
6989
  const startedFor = clockFor();
@@ -6996,7 +6999,10 @@ async function probeMcp(url, options = {}) {
6996
6999
  protocolVersion: null,
6997
7000
  serverName: null,
6998
7001
  serverVersion: null,
7002
+ instructions: null,
6999
7003
  tools: null,
7004
+ pages: null,
7005
+ truncated: false,
7000
7006
  note: "never answered and never gave up"
7001
7007
  }),
7002
7008
  options.deadlineMs ?? DEADLINE_MS
@@ -7008,6 +7014,36 @@ async function probeMcp(url, options = {}) {
7008
7014
  clearTimeout(timer);
7009
7015
  }
7010
7016
  }
7017
+ async function walkTools(send, session) {
7018
+ const tools = [];
7019
+ let cursor = null;
7020
+ let pages = 0;
7021
+ let status = 200;
7022
+ for (; ; ) {
7023
+ const asked = request(2 + pages, "tools/list", cursor === null ? void 0 : { cursor });
7024
+ const listed = await turn(await send(asked, session), "tools/list");
7025
+ if (listed.kind === "refused") {
7026
+ return {
7027
+ kind: "refused",
7028
+ reach: listed.reach,
7029
+ status: listed.status,
7030
+ note: "it opened but would not list"
7031
+ };
7032
+ }
7033
+ if (listed.kind === "broken")
7034
+ return { kind: "broken", status: listed.status, note: listed.note };
7035
+ tools.push(...toolsFrom(listed.value));
7036
+ status = listed.status;
7037
+ pages += 1;
7038
+ const next = text(listed.value.nextCursor);
7039
+ if (next === null || next === cursor)
7040
+ return { kind: "listed", status, tools, pages, truncated: false };
7041
+ if (pages >= MAX_PAGES || tools.length >= MAX_TOOLS) {
7042
+ return { kind: "listed", status, tools, pages, truncated: true };
7043
+ }
7044
+ cursor = next;
7045
+ }
7046
+ }
7011
7047
  async function handshake(url, options) {
7012
7048
  const doFetch = options.fetchImpl ?? fetch;
7013
7049
  const clock = options.now ?? Date.now;
@@ -7019,7 +7055,10 @@ async function handshake(url, options) {
7019
7055
  protocolVersion: null,
7020
7056
  serverName: null,
7021
7057
  serverVersion: null,
7022
- tools: null
7058
+ instructions: null,
7059
+ tools: null,
7060
+ pages: null,
7061
+ truncated: false
7023
7062
  };
7024
7063
  const send = (body, sessionId) => doFetch(url, {
7025
7064
  ...initFor(body, sessionId, userAgent),
@@ -7053,34 +7092,28 @@ async function handshake(url, options) {
7053
7092
  ...base,
7054
7093
  protocolVersion: text(hello.value.protocolVersion),
7055
7094
  serverName: text(info.name),
7056
- serverVersion: text(info.version)
7095
+ serverVersion: text(info.version),
7096
+ instructions: text(hello.value.instructions)
7057
7097
  };
7058
7098
  await send(notification("notifications/initialized"), session).catch(() => void 0);
7059
- const listed = await turn(await send(request(2, "tools/list"), session), "tools/list");
7060
- if (listed.kind === "refused") {
7061
- return {
7062
- ...said,
7063
- reach: listed.reach,
7064
- httpStatus: listed.status,
7065
- handshakeMs: took(),
7066
- note: "it opened but would not list"
7067
- };
7068
- }
7069
- if (listed.kind === "broken") {
7099
+ const walked = await walkTools(send, session);
7100
+ if (walked.kind !== "listed") {
7070
7101
  return {
7071
7102
  ...said,
7072
- reach: "error",
7073
- httpStatus: listed.status,
7103
+ reach: walked.kind === "refused" ? walked.reach : "error",
7104
+ httpStatus: walked.status,
7074
7105
  handshakeMs: took(),
7075
- note: listed.note
7106
+ note: walked.note
7076
7107
  };
7077
7108
  }
7078
7109
  return {
7079
7110
  ...said,
7080
7111
  reach: "readable",
7081
- httpStatus: listed.status,
7112
+ httpStatus: walked.status,
7082
7113
  handshakeMs: took(),
7083
- tools: toolsFrom(listed.value),
7114
+ tools: walked.tools,
7115
+ pages: walked.pages,
7116
+ truncated: walked.truncated,
7084
7117
  note: null
7085
7118
  };
7086
7119
  } catch (err) {
@@ -7096,7 +7129,7 @@ async function handshake(url, options) {
7096
7129
  }
7097
7130
  function toolsDigest(tools) {
7098
7131
  const canonical = JSON.stringify(
7099
- [...tools].map((t) => [t.name, t.description ?? "", t.hasInputSchema]).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)
7132
+ [...tools].map((t) => [t.name, t.description ?? "", t.inputSchema !== null]).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)
7100
7133
  );
7101
7134
  return createHash("sha256").update(canonical).digest("hex");
7102
7135
  }
@@ -7146,7 +7179,7 @@ function checksFor(seen) {
7146
7179
  return checks;
7147
7180
  }
7148
7181
  checks.push(pass("tools", "listed its tools", `${seen.tools.length} tool(s)`));
7149
- const bare = seen.tools.filter((t) => !t.hasInputSchema).map((t) => t.name);
7182
+ const bare = seen.tools.filter((t) => t.inputSchema === null).map((t) => t.name);
7150
7183
  checks.push(
7151
7184
  bare.length === 0 ? pass("input-schemas", "every tool declared an input schema") : fail(
7152
7185
  "input-schemas",
@@ -7441,6 +7474,19 @@ ${body}`);
7441
7474
  verdict: verdictOf(checks)
7442
7475
  };
7443
7476
  }
7477
+ function askedForPayment(result) {
7478
+ return result.checks.some((c) => c.id === "status_402" && c.status === "pass");
7479
+ }
7480
+ async function probeEitherVerb(run, explicit) {
7481
+ const verbs = explicit === void 0 ? ["GET", "POST"] : [explicit.toUpperCase()];
7482
+ let first;
7483
+ for (const method of verbs) {
7484
+ const attempt = await run(method);
7485
+ if (askedForPayment(attempt)) return attempt;
7486
+ first ??= attempt;
7487
+ }
7488
+ return first;
7489
+ }
7444
7490
 
7445
7491
  // src/report.ts
7446
7492
  var ANSI = {
@@ -7510,7 +7556,7 @@ var USAGE = `
7510
7556
  same form the public record uses.
7511
7557
 
7512
7558
  --mcp handshake a remote mcp server instead of an x402 endpoint
7513
- --method <verb> default POST
7559
+ --method <verb> tries get then post when not given
7514
7560
  --body <json|@file> default {}
7515
7561
  --json machine readable output
7516
7562
  --timeout <ms> default 15000
@@ -7559,17 +7605,18 @@ async function main() {
7559
7605
  ...values["user-agent"] ? { userAgent: values["user-agent"] } : {}
7560
7606
  };
7561
7607
  const rawBody = values.body ?? "{}";
7562
- const result = values.mcp ? await probeMcpEndpoint(shared) : await probe({
7563
- ...shared,
7564
- method: values.method?.toUpperCase() ?? "POST",
7565
- body: rawBody.startsWith("@") ? readFileSync(rawBody.slice(1), "utf8") : rawBody
7566
- });
7608
+ const body = rawBody.startsWith("@") ? readFileSync(rawBody.slice(1), "utf8") : rawBody;
7609
+ const found = await probeEitherVerb(
7610
+ (method) => probe({ ...shared, method, body }),
7611
+ values.method
7612
+ );
7613
+ const out = values.mcp ? await probeMcpEndpoint(shared) : found;
7567
7614
  stdout.write(
7568
- values.json ? `${formatJson(result)}
7569
- ` : formatText(result, shouldColour(env, stdout.isTTY === true))
7615
+ values.json ? `${formatJson(out)}
7616
+ ` : formatText(out, shouldColour(env, stdout.isTTY === true))
7570
7617
  );
7571
- if (!result.reachable) exit(2);
7572
- exit(result.verdict === "pass" ? 0 : 1);
7618
+ if (!out.reachable) exit(2);
7619
+ exit(out.verdict === "pass" ? 0 : 1);
7573
7620
  }
7574
7621
  main().catch((err) => {
7575
7622
  stdout.write(`${err.message}
package/npm/index.js CHANGED
@@ -7099,7 +7099,8 @@ function toolsFrom(result) {
7099
7099
  {
7100
7100
  name,
7101
7101
  description: text(tool.description),
7102
- hasInputSchema: typeof tool.inputSchema === "object" && tool.inputSchema !== null
7102
+ inputSchema: tool.inputSchema ?? null,
7103
+ outputSchema: tool.outputSchema ?? null
7103
7104
  }
7104
7105
  ];
7105
7106
  });
@@ -7125,6 +7126,8 @@ async function turn(response, method) {
7125
7126
  };
7126
7127
  }
7127
7128
  var DEADLINE_MS = 45e3;
7129
+ var MAX_PAGES = 20;
7130
+ var MAX_TOOLS = 2e3;
7128
7131
  async function probeMcp(url, options = {}) {
7129
7132
  const clockFor = options.now ?? Date.now;
7130
7133
  const startedFor = clockFor();
@@ -7140,7 +7143,10 @@ async function probeMcp(url, options = {}) {
7140
7143
  protocolVersion: null,
7141
7144
  serverName: null,
7142
7145
  serverVersion: null,
7146
+ instructions: null,
7143
7147
  tools: null,
7148
+ pages: null,
7149
+ truncated: false,
7144
7150
  note: "never answered and never gave up"
7145
7151
  }),
7146
7152
  options.deadlineMs ?? DEADLINE_MS
@@ -7152,6 +7158,36 @@ async function probeMcp(url, options = {}) {
7152
7158
  clearTimeout(timer);
7153
7159
  }
7154
7160
  }
7161
+ async function walkTools(send, session) {
7162
+ const tools = [];
7163
+ let cursor = null;
7164
+ let pages = 0;
7165
+ let status = 200;
7166
+ for (; ; ) {
7167
+ const asked = request(2 + pages, "tools/list", cursor === null ? void 0 : { cursor });
7168
+ const listed = await turn(await send(asked, session), "tools/list");
7169
+ if (listed.kind === "refused") {
7170
+ return {
7171
+ kind: "refused",
7172
+ reach: listed.reach,
7173
+ status: listed.status,
7174
+ note: "it opened but would not list"
7175
+ };
7176
+ }
7177
+ if (listed.kind === "broken")
7178
+ return { kind: "broken", status: listed.status, note: listed.note };
7179
+ tools.push(...toolsFrom(listed.value));
7180
+ status = listed.status;
7181
+ pages += 1;
7182
+ const next = text(listed.value.nextCursor);
7183
+ if (next === null || next === cursor)
7184
+ return { kind: "listed", status, tools, pages, truncated: false };
7185
+ if (pages >= MAX_PAGES || tools.length >= MAX_TOOLS) {
7186
+ return { kind: "listed", status, tools, pages, truncated: true };
7187
+ }
7188
+ cursor = next;
7189
+ }
7190
+ }
7155
7191
  async function handshake(url, options) {
7156
7192
  const doFetch = options.fetchImpl ?? fetch;
7157
7193
  const clock = options.now ?? Date.now;
@@ -7163,7 +7199,10 @@ async function handshake(url, options) {
7163
7199
  protocolVersion: null,
7164
7200
  serverName: null,
7165
7201
  serverVersion: null,
7166
- tools: null
7202
+ instructions: null,
7203
+ tools: null,
7204
+ pages: null,
7205
+ truncated: false
7167
7206
  };
7168
7207
  const send = (body, sessionId) => doFetch(url, {
7169
7208
  ...initFor(body, sessionId, userAgent),
@@ -7197,34 +7236,28 @@ async function handshake(url, options) {
7197
7236
  ...base,
7198
7237
  protocolVersion: text(hello.value.protocolVersion),
7199
7238
  serverName: text(info.name),
7200
- serverVersion: text(info.version)
7239
+ serverVersion: text(info.version),
7240
+ instructions: text(hello.value.instructions)
7201
7241
  };
7202
7242
  await send(notification("notifications/initialized"), session).catch(() => void 0);
7203
- const listed = await turn(await send(request(2, "tools/list"), session), "tools/list");
7204
- if (listed.kind === "refused") {
7243
+ const walked = await walkTools(send, session);
7244
+ if (walked.kind !== "listed") {
7205
7245
  return {
7206
7246
  ...said,
7207
- reach: listed.reach,
7208
- httpStatus: listed.status,
7209
- handshakeMs: took(),
7210
- note: "it opened but would not list"
7211
- };
7212
- }
7213
- if (listed.kind === "broken") {
7214
- return {
7215
- ...said,
7216
- reach: "error",
7217
- httpStatus: listed.status,
7247
+ reach: walked.kind === "refused" ? walked.reach : "error",
7248
+ httpStatus: walked.status,
7218
7249
  handshakeMs: took(),
7219
- note: listed.note
7250
+ note: walked.note
7220
7251
  };
7221
7252
  }
7222
7253
  return {
7223
7254
  ...said,
7224
7255
  reach: "readable",
7225
- httpStatus: listed.status,
7256
+ httpStatus: walked.status,
7226
7257
  handshakeMs: took(),
7227
- tools: toolsFrom(listed.value),
7258
+ tools: walked.tools,
7259
+ pages: walked.pages,
7260
+ truncated: walked.truncated,
7228
7261
  note: null
7229
7262
  };
7230
7263
  } catch (err) {
@@ -7240,7 +7273,7 @@ async function handshake(url, options) {
7240
7273
  }
7241
7274
  function toolsDigest(tools) {
7242
7275
  const canonical = JSON.stringify(
7243
- [...tools].map((t) => [t.name, t.description ?? "", t.hasInputSchema]).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)
7276
+ [...tools].map((t) => [t.name, t.description ?? "", t.inputSchema !== null]).sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)
7244
7277
  );
7245
7278
  return createHash("sha256").update(canonical).digest("hex");
7246
7279
  }
@@ -7290,7 +7323,7 @@ function checksFor(seen) {
7290
7323
  return checks;
7291
7324
  }
7292
7325
  checks.push(pass2("tools", "listed its tools", `${seen.tools.length} tool(s)`));
7293
- const bare = seen.tools.filter((t) => !t.hasInputSchema).map((t) => t.name);
7326
+ const bare = seen.tools.filter((t) => t.inputSchema === null).map((t) => t.name);
7294
7327
  checks.push(
7295
7328
  bare.length === 0 ? pass2("input-schemas", "every tool declared an input schema") : fail2(
7296
7329
  "input-schemas",
@@ -1,2 +1,2 @@
1
1
  export { JSON_RPC, lastEventData, notification, PREFERRED_VERSION, PROTOCOL_VERSIONS, type RpcResult, readAnswer, request, } from './frame.js';
2
- export { CLIENT, HANDSHAKE_TIMEOUT_MS, INITIALIZE, initFor, type McpObservation, type ProbeOptions, probeMcp, type Reach, reachFor, type Tool, toolsDigest, toolsFrom, } from './probe.js';
2
+ export { CLIENT, definitionDigest, definitionOf, HANDSHAKE_TIMEOUT_MS, INITIALIZE, initFor, MAX_PAGES, MAX_TOOLS, type McpObservation, type ProbeOptions, probeMcp, type Reach, reachFor, type Tool, toolsDigest, toolsFrom, } from './probe.js';
@@ -7,7 +7,8 @@ export type Reach = 'readable' | 'auth_required' | 'payment_required' | 'dead' |
7
7
  export type Tool = {
8
8
  readonly name: string;
9
9
  readonly description: string | null;
10
- readonly hasInputSchema: boolean;
10
+ readonly inputSchema: unknown;
11
+ readonly outputSchema: unknown;
11
12
  };
12
13
  export type McpObservation = {
13
14
  readonly url: string;
@@ -18,7 +19,10 @@ export type McpObservation = {
18
19
  readonly protocolVersion: string | null;
19
20
  readonly serverName: string | null;
20
21
  readonly serverVersion: string | null;
22
+ readonly instructions: string | null;
21
23
  readonly tools: readonly Tool[] | null;
24
+ readonly pages: number | null;
25
+ readonly truncated: boolean;
22
26
  readonly note: string | null;
23
27
  };
24
28
  export type ProbeOptions = {
@@ -40,5 +44,9 @@ export declare const INITIALIZE: {
40
44
  export declare function toolsFrom(result: Record<string, unknown>): Tool[];
41
45
  export declare function reachFor(status: number): Reach | null;
42
46
  export declare const DEADLINE_MS = 45000;
47
+ export declare const MAX_PAGES = 20;
48
+ export declare const MAX_TOOLS = 2000;
43
49
  export declare function probeMcp(url: string, options?: ProbeOptions): Promise<McpObservation>;
44
50
  export declare function toolsDigest(tools: readonly Tool[]): string;
51
+ export declare function definitionOf(seen: McpObservation): string;
52
+ export declare function definitionDigest(seen: McpObservation): string;
package/npm/probe.d.ts CHANGED
@@ -28,4 +28,6 @@ export type ProbeResult = {
28
28
  readonly verdict: 'pass' | 'fail';
29
29
  };
30
30
  export declare function probe(options: ProbeOptions): Promise<ProbeResult>;
31
+ export declare function askedForPayment(result: ProbeResult): boolean;
32
+ export declare function probeEitherVerb(run: (method: string) => Promise<ProbeResult>, explicit?: string): Promise<ProbeResult>;
31
33
  //# sourceMappingURL=probe.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAA8C,MAAM,aAAa,CAAC;AAGrF,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAClC,CAAC;AAgBF,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA+DvE"}
1
+ {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,KAAK,EAA8C,MAAM,aAAa,CAAC;AAGrF,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC,MAAM,MAAM,YAAY,GAAG;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC1F,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;CAClC,CAAC;AAgBF,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CA+DvE;AAGD,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAE5D;AAGD,wBAAsB,eAAe,CACpC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,EAC7C,QAAQ,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,WAAW,CAAC,CAStB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teppi-check",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Probe any paid endpoint and print what it actually returns for the money. Reproduces any entry in the Teppi record.",
5
5
  "keywords": [
6
6
  "x402",