@linkbunny/mcp 0.1.5 → 0.1.6

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
@@ -4,10 +4,10 @@ A local stdio MCP server that lets your coding agent run LinkBunny nofollow link
4
4
 
5
5
  Its official MCP Registry name is `com.getlinkbunny/exchange`.
6
6
 
7
- These examples pin the `0.1.5` release.
7
+ These examples pin the `0.1.6` release.
8
8
 
9
9
  ```sh
10
- npx -y @linkbunny/mcp@0.1.5
10
+ npx -y @linkbunny/mcp@0.1.6
11
11
  ```
12
12
 
13
13
  Your MCP client starts this process and communicates over stdin/stdout. Running the command alone waits for protocol input. npm hosts package files; no LinkBunny MCP process is hosted. API requests go only to `https://api.getlinkbunny.com/v1` over HTTPS. There is no endpoint override, daemon, polling, automatic retry, publication, or tool chaining.
@@ -25,7 +25,7 @@ For [Codex](https://developers.openai.com/codex/mcp), after authorization merge
25
25
  ```toml
26
26
  [mcp_servers.linkbunny]
27
27
  command = "npx"
28
- args = ["-y", "@linkbunny/mcp@0.1.5", "--token-file", "/absolute/project/.env.linkbunny"]
28
+ args = ["-y", "@linkbunny/mcp@0.1.6", "--token-file", "/absolute/project/.env.linkbunny"]
29
29
  ```
30
30
 
31
31
  Run `codex mcp list` from the intended project to check registration. Have the owner complete native trust, restart the client, and begin a fresh backing session in Codex or Agent Control before discovery. Same-process hot reload is not proven. Use `/mcp` to check the active server.
@@ -40,7 +40,7 @@ For [Claude Code](https://code.claude.com/docs/en/mcp), after authorization merg
40
40
  "command": "npx",
41
41
  "args": [
42
42
  "-y",
43
- "@linkbunny/mcp@0.1.5",
43
+ "@linkbunny/mcp@0.1.6",
44
44
  "--token-file",
45
45
  "/absolute/project/.env.linkbunny"
46
46
  ]
@@ -59,7 +59,7 @@ For [VS Code](https://code.visualstudio.com/docs/agents/reference/mcp-configurat
59
59
  "linkbunny": {
60
60
  "type": "stdio",
61
61
  "command": "npx",
62
- "args": ["-y", "@linkbunny/mcp@0.1.5"],
62
+ "args": ["-y", "@linkbunny/mcp@0.1.6"],
63
63
  "envFile": "${workspaceFolder}/.env.linkbunny"
64
64
  }
65
65
  }
@@ -82,7 +82,7 @@ An explicit file takes precedence over an inherited token; invalid files never f
82
82
 
83
83
  A package cached or downloaded by npm is not proof that a server is registered. Check initialization separately after saving the registration. Tokens saved in a secret store or repository environment file are not automatically loaded by the client.
84
84
 
85
- In the fresh session, ask the configured client to perform `initialize`, `tools/list`, `resources/list`, and `resources/read` for `linkbunny://guidance/skill`, then call `get_status` once. Expect server version `0.1.5`, exactly the six tools below, the guidance text, and a status result. `get_status` is read-only and proves token admission without reserving anything. Do not call any other tool to test configuration: even `check_in` can reserve an assignment. If a client cannot list or read resources, report that part as unverified; reading the web skill does not verify MCP resource access.
85
+ In the fresh session, ask the configured client to perform `initialize`, `tools/list`, `resources/list`, and `resources/read` for `linkbunny://guidance/skill`, then call `get_status` once. Expect server version `0.1.6`, exactly the six tools below, the guidance text, and a status result. `get_status` is read-only and proves token admission without reserving anything. Do not call any other tool to test configuration: even `check_in` can reserve an assignment. If a client cannot list or read resources, report that part as unverified; reading the web skill does not verify MCP resource access.
86
86
 
87
87
  Discovery and resource reads make no LinkBunny API requests. Startup validates token format locally, so only `get_status` proves API token admission and shows subscription state. For isolated discovery-only testing, use the synthetic example `LINKBUNNY_API_TOKEN=synthetic-discovery-only-not-a-real-token-00000000`. It passes the local format check but cannot authorize real API activity. Never substitute a production token merely to test package startup. Discovery-only tests must not invoke `create_profile`, `update_profile`, `check_in`, `report_assignment`, or `reject_assignment`.
88
88
 
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ var STATUS_PAGE_LIMIT = 100;
18
18
  var REQUEST_TIMEOUT_MS = 1e4;
19
19
  var MAX_RESPONSE_BYTES = 1048576;
20
20
  var SKILL_URI = "linkbunny://guidance/skill";
21
- var VERSION = "0.1.5";
21
+ var VERSION = "0.1.6";
22
22
 
23
23
  // src/privacy.ts
24
24
  function redact({
@@ -32,7 +32,7 @@ function redact({
32
32
  var errorMessages = {
33
33
  invalid_request: "Request payload or path is invalid. Review the canonical guidance and correct the authorized request.",
34
34
  unauthorized: "Credential rejected. Ask the owner to check their token in the private Account page.",
35
- forbidden: "A paid LinkBunny subscription is required through https://getlinkbunny.com/account. Account and billing operations are not available through this MCP.",
35
+ forbidden: "The free exchange limit is reached or a paid LinkBunny subscription is required through https://getlinkbunny.com/account. Account and billing operations are not available through this MCP.",
36
36
  not_found: "The owned resource is unavailable. Confirm the retained canonical ID with the owner.",
37
37
  profile_conflict: "A live profile already exists for this domain. Recover its canonical ID from the private Account page.",
38
38
  idempotency_conflict: "A previous report or rejection has different details. Do not change details to force a retry.",
@@ -323,7 +323,7 @@ function createServer({
323
323
  {
324
324
  name: "create_profile",
325
325
  title: "Create profile",
326
- description: "Register an owner-managed site only after specific registration authorization. Requires subscription. Retain the returned canonical profileID privately; await review without polling.",
326
+ description: "Register an owner-managed site only after specific registration authorization. Free accounts get one site. Retain the returned canonical profileID privately; await review without polling.",
327
327
  input: createInput,
328
328
  response: createResponse,
329
329
  method: "POST",
@@ -478,13 +478,17 @@ function statusNextAction(result) {
478
478
  }
479
479
  const { account, profiles, nextOffset } = result.data;
480
480
  const noAutomaticWrites = "Do not run any other LinkBunny tool automatically.";
481
- if (!account.subscriptionActive) {
482
- return `Tell the owner the paid LinkBunny subscription is not active; they can subscribe at ${ACCOUNT_URL}. Registration and check-in are unavailable until then. Any pending assignment listed here can still be reported or rejected with specific owner authorization. ${noAutomaticWrites}`;
483
- }
481
+ const freeExchange = account.subscriptionActive ? [] : [
482
+ `This account has no paid subscription, so it uses the free exchange: one site, one reported placement and one received backlink. Each direction stops on its own: after the first placement is successfully reported, check_in issues no new assignments, and after the first backlink is reported, the site is no longer picked as a target for new assignments; the other direction stays open. Already issued assignments can still be reported within their normal window and settle, so either count can go above one. A 403 from create_profile or check_in means a free exchange limit is reached; the owner can subscribe at ${ACCOUNT_URL}.`
483
+ ];
484
484
  if (account.profileCount === 0) {
485
- return `No sites are registered. Registering a site with create_profile needs the owner's specific registration authorization. ${noAutomaticWrites}`;
485
+ return [
486
+ ...freeExchange,
487
+ `No sites are registered. Registering a site with create_profile needs the owner's specific registration authorization. ${noAutomaticWrites}`
488
+ ].join(" ");
486
489
  }
487
490
  const steps = [
491
+ ...freeExchange,
488
492
  ...profiles.some((profile) => profile.pendingAssignment) ? [
489
493
  "Present each existing pending assignment to the owner for review instead of checking in to reserve more. Publication, report, and rejection each need separate owner authorization."
490
494
  ] : [],
package/dist/skill.md CHANGED
@@ -15,10 +15,15 @@ publishing through the site's normal workflow, or rejects the request.
15
15
 
16
16
  1. A LinkBunny account is required. The human may create an account or log in at
17
17
  `https://getlinkbunny.com`; an agent may do so only with explicitly authorized browser control.
18
- 2. An eligible paid subscription is required before entitled operations. The human must authorize
19
- starting, changing, or cancelling billing; an authorized browser-capable agent may operate the
20
- website UI for that approved action.
21
- 3. With an active subscription, create an API token in the account UI. The human must authorize
18
+ 2. A new account can try one exchange free: one site, one completed link placement and one received
19
+ backlink, no card. Each direction stops on its own: after the site's first placement is
20
+ successfully reported, it gets no new assignments to place, and after its first backlink is
21
+ reported, it is no longer picked as the target of new assignments. The other direction stays
22
+ open. Assignments already issued can still be reported within their normal window and settle,
23
+ so a free site can end up with more than one placement or backlink. The paid subscription removes that limit and covers up to 10 sites. The human
24
+ must authorize starting, changing, or cancelling billing; an authorized browser-capable agent may
25
+ operate the website UI for that approved action.
26
+ 3. Create an API token in the account UI. The human must authorize
22
27
  each creation, rotation, or revocation; an authorized browser-capable agent may perform it. Copy
23
28
  the token once into an owner-approved secret store and keep it secret.
24
29
  4. Use that token for the public API workflow below. The public API does not provide signup, login,
@@ -35,14 +40,15 @@ may carry out an authorized API or site action only within the approval given.
35
40
  When the owner asks you to set up LinkBunny and has no account or API token yet:
36
41
 
37
42
  1. Plan locally. Inspect the project and propose one HTTPS target URL and one HTTPS area of the
38
- site where nofollow links can go, both on the same registrable domain. Tell the owner the price
39
- ($20/month for up to 10 sites, no per-link fees), that profiles are reviewed before they can
40
- match, that some check-ins return no request, and which later steps need their approval. Make
41
- no LinkBunny API call while there is no token.
43
+ site where nofollow links can go, both on the same registrable domain. Tell the owner the first
44
+ exchange is free for one site, the price after that ($20/month for up to 10 sites, no per-link
45
+ fees), that profiles are reviewed before they can match, that some check-ins return no request,
46
+ and which later steps need their approval. Make no LinkBunny API call while there is no token.
42
47
  2. With the owner's OK, open `https://getlinkbunny.com/login?redirect=%2Faccount%3Fsetup%3Dagent`
43
48
  in their browser, or print it when you cannot open a browser (for example in a cloud or remote
44
49
  session). Opening the link is not browser control: do not read, click, fill, or otherwise
45
- operate the page. The owner signs in, subscribes, and creates the API token there.
50
+ operate the page. The owner signs in and creates the API token there. Subscribing is optional
51
+ for the free exchange.
46
52
  3. With the owner's OK, create a project file `.env.linkbunny` containing only an empty
47
53
  `LINKBUNNY_API_TOKEN=` line and make sure Git ignores it, or use another secret store the owner
48
54
  chooses. The owner pastes the token there. Never ask for the token in chat, and never print,
@@ -51,12 +57,12 @@ When the owner asks you to set up LinkBunny and has no account or API token yet:
51
57
  token out of command arguments and output, for example:
52
58
  `tr -d '\r' < .env.linkbunny | sed -nE 's/^(export )?LINKBUNNY_API_TOKEN="?([A-Za-z0-9._~-]+)"?$/header = "Authorization: Bearer \2"/p' | curl -sS -w '\nHTTP %{http_code}\n' --config - https://api.getlinkbunny.com/v1/me`.
53
59
  If the LinkBunny MCP server is already configured with that token file, its `get_status` tool
54
- makes the same read. `subscriptionActive: true` confirms setup. `401` means the token is missing
55
- or wrong in the file; `subscriptionActive: false` means the subscription is not confirmed yet,
56
- so ask the owner to finish or refresh it on the account page. Do not poll; wait until the owner
57
- says it is done again.
58
- 5. Only after `subscriptionActive: true`, continue with "A — Create a profile". Ask the owner
59
- before registering the site.
60
+ makes the same read. A `200` response confirms setup. `subscriptionActive: false` with
61
+ `siteLimit: 1` means the account is on the free exchange; `subscriptionActive: true` means the
62
+ paid plan is active. `401` means the token is missing or wrong in the file. Do not poll; wait
63
+ until the owner says it is done again.
64
+ 5. After a `200` status read, continue with "A — Create a profile". Ask the owner before
65
+ registering the site.
60
66
 
61
67
  ## Activation and approval gates
62
68
 
@@ -112,8 +118,8 @@ Present an existing pending assignment for owner review rather than checking in
112
118
 
113
119
  After specific authorization, `POST /profiles` with `targetURL`, `requestedAnchor`, one documented
114
120
  `category`, and `inventoryPrefix`. Both URLs must be public HTTPS URLs without credentials or
115
- fragments, on the same registrable domain. This operation requires an active subscription. A
116
- successful Domain Rating lookup returns `201` with status `pending_review`. LinkBunny reviews each
121
+ fragments, on the same registrable domain. Without a subscription, an account can register one
122
+ site for its free exchange. A successful Domain Rating lookup returns `201` with status `pending_review`. LinkBunny reviews each
117
123
  new profile once before it can match as a source or target. Tell the owner review is pending and
118
124
  suggest asking the agent to check again after the advisory interval or once approval is confirmed.
119
125
  Immediately record and retain the response's canonical `profileID` in the owner's approved private
@@ -144,11 +150,13 @@ only when no more specific category fits:
144
150
  After specific authorization, `PATCH /profiles/:profileID` accepts the same fields. Changing the
145
151
  target or inventory URL materially resets the profile to Domain Rating lookup and one-time review;
146
152
  it cannot match during re-review. Anchor- or category-only edits preserve an existing approval.
153
+ Without a subscription, a URL change made within an hour of the site's creation or previous URL
154
+ change waits up to an hour for its Domain Rating lookup and stays `pending` until then.
147
155
 
148
156
  ### B — Check in
149
157
 
150
- After specific authorization, `POST /profiles/:profileID/check-in`. This operation requires an
151
- active subscription. The response contains the same existing pending assignment, one newly
158
+ After specific authorization, `POST /profiles/:profileID/check-in`. Without a subscription, the
159
+ free exchange allows check-ins until the site's one placement is reported. The response contains the same existing pending assignment, one newly
152
160
  reserved assignment, or `{ "assignment": null }`. A profile awaiting review instead returns
153
161
  `{ "assignment": null, "status": "profile_pending_review", "message": "This site is awaiting marketplace review.", "retryAfterSeconds": 3600 }`;
154
162
  the one-hour interval is advisory, and every check-in still requires specific owner authorization.
@@ -240,11 +248,13 @@ may return `409 terminal_conflict`. Expected errors use `{ "error": { "code", "m
240
248
  400 invalid request, 401 credential failure, 403 entitlement failure, 404 unavailable owned
241
249
  resource, or 409 terminal conflict.
242
250
 
243
- When create-profile or check-in returns a subscription-required `403`, tell the owner that a paid
244
- LinkBunny subscription is required and must be completed through the account website at
245
- `https://getlinkbunny.com/account`. Do not imply that signup, billing, or token creation is
246
- available through the public API. Report and reject remain available for already-issued
247
- assignments so they can be settled after entitlement ends.
251
+ When create-profile, check-in, or profile update returns a `403` that mentions the free exchange or a
252
+ subscription, relay its message: the free exchange covers one site and one reported placement, and
253
+ the paid subscription at `https://getlinkbunny.com/account` adds more. A free site that already
254
+ placed its link still stays eligible to receive its one backlink when a match comes up. Do not
255
+ imply that signup, billing, or token creation is available through the public API. Report and
256
+ reject never depend on a subscription: any issued assignment can be reported or reconsidered
257
+ within the usual windows, including after entitlement ends or the free exchange is used.
248
258
 
249
259
  Pending assignments expire at their seven-day deadline. Expiration releases the reservation but
250
260
  does not permanently exclude the directional pair. Report completion for the exact original
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@linkbunny/mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@linkbunny/mcp",
9
- "version": "0.1.5",
9
+ "version": "0.1.6",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/server": "2.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linkbunny/mcp",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "mcpName": "com.getlinkbunny/exchange",
5
5
  "description": "Local stdio MCP server for LinkBunny nofollow link exchanges. Requires a LinkBunny account API token.",
6
6
  "type": "module",