baconservices-mcp 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/README.md CHANGED
@@ -22,15 +22,16 @@ spending limits.
22
22
  | `optimize_image` | Resizes so the longest side ≤ `max_width` (64–4096, default 1600) and encodes WebP at `quality` (40–95, default 80) | 0.01 USDC |
23
23
  | `image_palette` | The colours one image is mostly made of, as JSON: up to `count` (1–12, default 6) hex colours with their share, `include_neutrals` (default true) | 0.01 USDC |
24
24
  | `brand_from_url` | Reads one public web page (`url`) and returns its brand as JSON: name, description, logo URLs, colours, fonts, social profiles. No JavaScript runs; robots.txt is respected | 0.03 USDC |
25
+ | `vectorize_image` | Traces one image into an SVG of flat-colour paths: `colors` (2–32, default 16), `detail` (`smooth`, `balanced` or `detailed`, default `balanced`). Best for logos and icons | 0.05 USDC |
25
26
 
26
27
  Image tools take PNG, JPEG or WebP up to 8 MB, as `image_url` (public https) or `image_path` (a
27
- local file). `remove_background` and `optimize_image` return a signed download link (valid 24
28
- hours); `image_palette` and `brand_from_url` return their JSON result in the tool result. Add
28
+ local file). `remove_background`, `optimize_image` and `vectorize_image` return a signed download
29
+ link (valid 24 hours); `image_palette` and `brand_from_url` return their JSON result in the tool result. Add
29
30
  `save_to` to write either kind to disk. Prices come from Bacon's live catalog, and each paid tool
30
31
  states its current price in its description.
31
32
 
32
- `image_palette` and `brand_from_url` appear once Bacon's catalog publishes them with contract
33
- versions. A service the installed package doesn't understand is listed by `list_services` but
33
+ `image_palette`, `brand_from_url` and `vectorize_image` appear once Bacon's catalog publishes
34
+ them with contract versions. A service the installed package doesn't understand is listed by `list_services` but
34
35
  can't be called until you update the package.
35
36
 
36
37
  Free tools:
@@ -197,6 +198,12 @@ Commerce services, x402-paid capabilities, infrastructure, and backend implement
197
198
  separate services and are not licensed under the MIT License. Use of Bacon Services' hosted
198
199
  APIs and x402 services is governed by the [Bacon Services terms](https://baconservices.com/terms).
199
200
 
201
+ ## Support
202
+
203
+ For MCP, x402, or Agent Commerce support, contact Bacon Services:
204
+ https://baconservices.com/contact?topic=mcp. Please never send a wallet private key. Bugs in
205
+ this package can also be reported as issues on its repository.
206
+
200
207
  ## Trademark notice
201
208
 
202
209
  The MIT License applies to the source code in this repository only. "Bacon Services," the
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "baconservices-mcp",
3
- "version": "0.1.1",
4
- "description": "MCP server that lets an AI agent buy Bacon Services image operations (remove background, optimize for the web) per call in USDC over x402, with local spending limits.",
3
+ "version": "0.2.0",
4
+ "description": "MCP server that lets an AI agent buy Bacon Services tools per call in USDC over x402: remove a background, optimize an image for the web, read an image's colour palette, read a brand from a URL, trace an image into an SVG. With local spending limits.",
5
5
  "mcpName": "io.github.afmontoya/baconservices-mcp",
6
6
  "type": "module",
7
7
  "bin": {
@@ -28,6 +28,8 @@
28
28
  "base",
29
29
  "remove-background",
30
30
  "image-optimization",
31
+ "color-palette",
32
+ "brand-kit",
31
33
  "agent-payments"
32
34
  ],
33
35
  "homepage": "https://baconservices.com",
package/src/contracts.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // package will EXECUTE. A capability becomes a paid tool only when its catalog entry matches one
5
5
  // of these contracts exactly. A contract is the capability id, its behaviour `version`, its
6
6
  // `input_version` and `output_version`, an input type (one image, or one web page URL) with the
7
- // same option names, types and bounds, an output (an artifact file of one MIME type, or a JSON
7
+ // same option names, types, bounds and allowed values, an output (an artifact file of one MIME type, or a JSON
8
8
  // result), synchronous execution, and declared limits. Anything else — a new capability, a new
9
9
  // version, a changed schema, a catalog contract_version this package does not know — is still
10
10
  // shown by list_services, but is not executable until a package release that knows it.
@@ -81,6 +81,22 @@ export const CONTRACTS = [
81
81
  output: { kind: 'json', mime: 'application/json' },
82
82
  execution: 'sync',
83
83
  },
84
+ {
85
+ tool: 'vectorize_image',
86
+ id: 'vectorize',
87
+ version: 1,
88
+ inputVersion: 1,
89
+ outputVersion: 1,
90
+ title: 'Vectorize image',
91
+ summary: 'Traces one PNG, JPEG or WebP image into an SVG of filled paths with up to colors flat colours. Best for logos, icons and flat artwork; a photo comes back as a stylised poster. The SVG keeps the image\'s width and height (capped at 4096).',
92
+ input: 'image',
93
+ options: {
94
+ colors: { type: 'integer', minimum: 2, maximum: 32, default: 16, description: 'How many flat colours to trace with. 2 is black and white.' },
95
+ detail: { type: 'string', enum: ['smooth', 'balanced', 'detailed'], default: 'balanced', description: 'smooth: fewer, simpler shapes. detailed: closer to the source, larger file.' },
96
+ },
97
+ output: { kind: 'artifact', mime: 'image/svg+xml' },
98
+ execution: 'sync',
99
+ },
84
100
  ];
85
101
 
86
102
  export function contractId(id, version) {
@@ -149,8 +165,10 @@ export function checkEntry(entry, contract, expected) {
149
165
  reasons.push(`input properties are [${names}], expected [${Object.keys(expectedProperties).sort().join(',')}]`);
150
166
  } else {
151
167
  for (const [name, want] of Object.entries(expectedProperties)) {
152
- for (const key of ['type', 'minimum', 'maximum', 'default']) {
153
- if (want[key] !== properties[name][key]) {
168
+ for (const key of ['type', 'minimum', 'maximum', 'default', 'enum']) {
169
+ // An enum is compared whole: the same values in the same order.
170
+ const same = key === 'enum' ? JSON.stringify(want[key]) === JSON.stringify(properties[name][key]) : want[key] === properties[name][key];
171
+ if (!same) {
154
172
  reasons.push(`input ${name}.${key} is ${JSON.stringify(properties[name][key])}, expected ${JSON.stringify(want[key])}`);
155
173
  }
156
174
  }
package/src/payment.js CHANGED
@@ -567,7 +567,7 @@ export function prepareUrl(args, inputSchema) {
567
567
  return { body: { url: url.href }, identity: `page:${url.href}` };
568
568
  }
569
569
 
570
- /** The contract's options, defaults filled in: integers within their bounds, booleans as booleans. */
570
+ /** The contract's options, defaults filled in: integers within their bounds, booleans as booleans, named values from their list. */
571
571
  export function prepareOptions(args, contract) {
572
572
  const options = {};
573
573
  for (const [name, spec] of Object.entries(contract.options)) {
@@ -576,6 +576,10 @@ export function prepareOptions(args, contract) {
576
576
  if (typeof value !== 'boolean') {
577
577
  throw new Refusal(`${name} must be true or false.`);
578
578
  }
579
+ } else if (spec.enum) {
580
+ if (!spec.enum.includes(value)) {
581
+ throw new Refusal(`${name} must be one of: ${spec.enum.join(', ')}.`);
582
+ }
579
583
  } else if (!Number.isInteger(value) || value < spec.minimum || value > spec.maximum) {
580
584
  throw new Refusal(`${name} must be a whole number from ${spec.minimum} to ${spec.maximum}.`);
581
585
  }
package/src/server.js CHANGED
@@ -14,7 +14,7 @@ import { formatUsdc } from './money.js';
14
14
  import { Purchaser, Refusal } from './payment.js';
15
15
  import { balanceReader, loadWallet, redact } from './wallet.js';
16
16
 
17
- export const VERSION = '0.1.1';
17
+ export const VERSION = '0.2.0';
18
18
  const CATALOG_TTL_MS = 5 * 60 * 1000;
19
19
 
20
20
  const FREE_TOOLS = [